新聞中心
現(xiàn)在讓我們討論每種技術,一次一個。

龍崗網站建設公司成都創(chuàng)新互聯(lián)公司,龍崗網站設計制作,有大型網站制作公司豐富經驗。已為龍崗上千提供企業(yè)網站建設服務。企業(yè)網站搭建\外貿營銷網站建設要多少錢,請找那個售后服務好的龍崗做網站的公司定做!
純函數(shù)
純函數(shù)是在給定相同輸入的情況下始終返回相同輸出的函數(shù)。除了提供的輸入之外,它不依賴于任何外部變量,也不影響/更改任何外部變量。擁有純函數(shù)使測試變得更加容易,因為它們使測試變得超級容易,因為您可以隨時存根/模擬輸入并測試您的預期值。讓我們看看下面的例子
let name = "Yu DongSu";
const splitName = () => {
name = name.split(' ');
}
name = splitName();
console.log(name); // outputs [ 'Yu', 'DongSu' ]
雖然上面的代碼看起來很合適。不是開玩笑。這是因為該splitName函數(shù)依賴于一個名為的外部變量name,如果其他人開始更改此變量,該函數(shù)將splitName開始提供不同的輸出。使它成為一個非純函數(shù),因為我們仍然會調用splitName()它,但輸出會有所不同。
讓我們把它改成一個純函數(shù),看看它是什么樣子的:
let name = "Yu DongSu";
const splitName = (nameString) => {
return nameString.split(' ');
}
name = splitName(name);
console.log(name); // outputs [ 'Yu', 'DongSu' ]
通過上述更改,splitName現(xiàn)在是一個純函數(shù),因為:
- 它僅依賴于輸入(nameString輸入)。
- 它不會更改/重新分配任何外部變量。
更少或命名參數(shù)
使用函數(shù)時,我們經常使用位置參數(shù),這些參數(shù)必須在函數(shù)聲明中聲明時提供。例如,在 call中,如果不提供and arithmaticOp(num1, num2, operator),我們就無法提供operator參數(shù)。雖然這適用于這個例子,但對于許多功能來說,這會成為一個問題??紤]以下示例:
const createButton = (title, color, disabled, padding, margin, border, shadow) => {
console.log(title, color, disabled, padding, margin, border, shadow)
}查看上面的代碼,您已經可以看到,如果我們想在調用createButton+ 時將任何參數(shù)設為可選(使用默認值),那將是一場災難,可能看起來像這樣:
createButton('Sudongyu er', undefined /* optional color */, true ,'2px....', undefined /* optional margin*/);你可以看到上面的語句看起來一點也不干凈。此外,從函數(shù)調用語句中很難看出哪個參數(shù)對應于函數(shù)的哪個參數(shù)。所以這是我們可以遵循的做法:
- 如果我們有 2 個或更少的參數(shù),我們可以將它們保留為位置參數(shù)
- 否則,我們提供一個帶有鍵值對的對象
讓我們在上面的例子中使用這個技術,看看它是什么樣子的:
const createButton = ({title, color, disabled, padding, margin, border, shadow}) => {
console.log(title, color, disabled, padding, margin, border, shadow)
}
createButton({
title: 'Sudongyu er',
disabled: true,
shadow: '2px....'
});請注意,調用createButton函數(shù)的語句現(xiàn)在更簡潔了。我們可以很容易地看到鍵值對中的哪個值對應于函數(shù)的參數(shù)。耶耶!
對象/數(shù)組解構
考慮以下 javascript 示例,其中我們從對象中獲取一些屬性并分配給它們的各個變量:
const user = {
name: 'Sudongyu',
email: 'hi@xxx',
designation: 'Software Architect',
loves: 'The Code'
}
const name = user.name;
const email = user.email;
const loves = user.loves;在上面的例子中,多次使用這個user.*符號是非常令人惡心的。這就是對象解構的用武之地。我們可以使用對象解構將上面的示例更改如下:
const user = {
name: 'Sudongyu',
email: 'hi@xxx',
designation: 'Software Architect',
loves: 'The Code'
}
const {name, email, loves} = user;看!好多了。對?讓我們考慮另一個例子:
const getDetails = () => {
return ['xxx', 'sudongyu', 'Some Street', 'Some City', 'Some Zip', 'Some Country'];
}
const details = getDetails();
const uName = details[0];
const uEmail = details[1];
const uAddress = `${details[2]}, ${details[3]}, ${details[4]}, ${details[5]}`;
const uFirstName = uName.split(' ')[0];
const uLastName = uName.split(' ')[1];
啊。我什至討厭編寫上述示例的代碼。雖然不得不這樣做。您可以看到代碼看起來非常怪異且難以閱讀。我們可以使用 Array Destructuring 將其寫得更簡潔,如下所示:
const getDetails = () => {
return ['xxx', 'sudongyu', 'Some Street', 'Some City', 'Some Zip', 'Some Country'];
}
const [uName, uEmail, ...uAddressArr] = getDetails();
const uAddress = uAddressArr.join(', ');
const [uFirstName, uLastName] = uName.split('');
console.log({
uFirstName,
uLastName,
uEmail,
uAddress
});你可以看到這有多干凈!
避免硬編碼值
/**
* 阿巴阿巴
*
*
*
*
*
*/
setInterval(() => {
// do something
}, 86400000);
// WHAT IS THIS 86400000 ??? ????
看代碼的人可能不知道這個數(shù)字代表什么,它是如何計算的,以及它背后的業(yè)務邏輯是什么。我們可以創(chuàng)建一個常量,而不是硬編碼這個值,如下所示:
const DAY_IN_MILLISECONDS = 3600 * 24 * 1000; // 86400000
setInterval(() => {
// do something
}, DAY_IN_MILLISECONDS);
// now this makes sense
讓我們考慮另一個例子:
const createUser = (name, designation, type) => {
console.log({name, designation, type});
}
createUser('SudongYu', 'Software Architect', '1');
// WHAT IS this '1'? ????查看調用createUser方法。閱讀代碼的人很難理解這'1'代表什么。即type這是什么用戶。因此,我們可以創(chuàng)建一個我們擁有的用戶類型的對象映射,而不是在這里對值進行硬編碼'1',如下所示:
const USER_TYPES = {
REGULAR_EMPLOYEE: '1'
}
const createUser = (name, designation, type) => {
console.log({name, designation, type});
}
createUser('Sudongyu', 'Software Architect', USER_TYPES.REGULAR_EMPLOYEE);
// smoooooooth
避免使用簡寫變量名
速記變量在需要它們的地方才有意義。就像如果你有像xand這樣的位置坐標y,那是可行的。p但是,如果我們在沒有上下文的情況下創(chuàng)建像,t之類的變量c,那么真的很難閱讀、跟蹤和維護這樣的代碼。例如看這個例子:
const t = 25;
let users = ['Sudongyuer', 'xxx'];
users = users.map((user) => {
/**
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
return {
...user,
tax: user.salary * t / 100 // WHAT IS `t` again? ????
}
})
上面的例子表明,現(xiàn)在開發(fā)人員/讀者必須一直向上滾動或轉到定義來嘗試理解這個變量是什么。因此是不干凈的代碼。這也稱為對變量進行思維導圖,其中只有作者知道它們的含義。因此,我們可以給它一個適當?shù)拿Q,而不是簡寫變量名稱,如下所示:
const taxFactor = 25;
let users = ['Sudongyuer', 'xxx'];
users = users.map((user) => {
// some code
return {
...user,
tax: user.salary * taxFactor / 100
}
})
現(xiàn)在這更有意義了。
使用 Object.assign() 設置默認對象值
在某些情況下,您可能希望從另一個對象創(chuàng)建一個新對象,如果源對象沒有它們,則提供一些默認值。考慮以下示例:
const createButton = ({title, color, disabled, padding}) => {
const button = {};
button.color = color || '#333';
button.disabled = disabled || false;
button.title = title || '';
button.padding = padding || 0;
return button;
}
const buttonConfig = {
title: 'Click me!',
disabled: true
}
const newButton = createButton(buttonConfig);
console.log('newButton', newButton)
Object.assign()如果源對象提供了默認屬性,我們可以使用如下方式覆蓋默認屬性,而不是做所有這些:
const createButton = (config) => {
return {
...{
color: '#dcdcdc',
disabled: false,
title: '',
padding: 0
},
...config
};
}
const buttonConfig = {
title: 'Click me!',
disabled: true
}
const newButton = createButton(buttonConfig);
console.log('newButton', newButton)
使用方法鏈(尤其是類)
如果我們知道類/對象的用戶將一起使用多個函數(shù),則方法鏈接是一種很有用的技術。您可能已經在諸如 moment.js 之類的庫中看到了這一點。讓我們看一個例子:
class Player {
constructor (name, score, position) {
this.position = position;
this.score = score;
this.name = name;
}
setName(name) {
this.name = name;
}
setPosition(position) {
this.position = position;
}
setScore(score) {
this.score = score;
}
}
const player = new Player();
player.setScore(0);
player.setName('Sudongyuer');
player..setPosition([2, 0]);
console.log(player)
在上面的代碼中,您可以看到我們需要為播放器一起調用一堆函數(shù)。如果您的對象/類是這種情況,請使用方法鏈接。您需要做的就是從要鏈接的函數(shù)中返回對象的實例。上面的例子可以修改如下來實現(xiàn):
class Player {
constructor (name, score, position) {
this.position = position;
this.score = score;
this.name = name;
}
setName(name) {
this.name = name;
return this; // <-- THIS
}
setPosition(position) {
this.position = position;
return this; // <-- THIS
}
setScore(score) {
this.score = score;
return this; // <-- THIS
}
}
const player = new Player();
player.setScore(0).setName('Sudongyuer').setPosition([2, 0]);
// SUPER COOL
console.log(player)
在回調上使用 Promise
承諾讓我們的生活更輕松。幾年前我們有一個叫做回調地獄的東西,這使得代碼很難閱讀。它看起來像這樣:
圖片描述
即使我正在使用具有回調的庫,我也會嘗試在那里添加一個包裝器來保證這一點(是的,現(xiàn)在這是一個術語)。讓我們考慮以下示例:
const getSocials = (callback) => {
setTimeout(() => {
callback({socials: {youtube: 'xxx', twitter: 'xxx'}});
}, 1500);
}
const getBooks = (callback) => {
setTimeout(() => {
callback({books: ['React Cookbook']});
}, 1500);
}
const getDesignation = (callback) => {
setTimeout(() => {
callback({designation: 'Software Architect'});
}, 1500);
}
const getUser = (callback) => {
setTimeout(() => {
callback({user: 'Sudongyuer'});
}, 1500);
}
getUser(({user}) => {
console.log('user retrieved', user)
getDesignation(({designation}) => {
console.log('designation retrieved', designation)
getBooks(({books}) => {
console.log('books retrieved', books)
getSocials(({socials}) => {
console.log('socials retrieved', socials)
})
})
})
})
上述代碼中的所有函數(shù)都是異步的,它們會在 1.5 秒后發(fā)回數(shù)據。現(xiàn)在,如果涉及 15 個不同的功能,想象一下它會是什么樣子。可能就像我在上面分享的圖像。為了更好的可讀性,我們可以promisify我們的函數(shù)并使用promises,而不是這個回調地獄:
const getSocials = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve({socials: {youtube: 'xxx', twitter: 'xxx'}});
}, 1500);
})
}
const getBooks = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve({books: ['React Cookbook']});
}, 1500);
})
}
const getDesignation = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve({designation: 'Software Architect'});
}, 1500);
})
}
const getUser = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve({user: 'Sudongyuer'});
}, 1500);
})
}
getUser()
.then(({user}) => {
console.log('user retrieved', user);
return getDesignation();
})
.then(({designation}) => {
console.log('designation retrieved', designation)
return getBooks();
})
.then(({books}) => {
console.log('books retrieved', books);
return getSocials();
})
.then(({socials}) => {
console.log('socials retrieved', socials)
})您可以看到代碼現(xiàn)在已經非??勺x,因為所有語句都縮進并顯示了在每個步驟.then()中檢索到的數(shù)據。.then()我們可以很容易地看到使用這種語法的步驟,因為每次.then()調用都會返回下一個函數(shù)調用及其承諾。
現(xiàn)在我們可以把它提升一個檔次,讓我們的代碼更具可讀性。如何?通過使用async await. 我們將修改我們的代碼如下來實現(xiàn):
const getSocials = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve({socials: {youtube: 'xxx', twitter: 'xxx'}});
}, 1500);
})
}
const getBooks = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve({books: ['React Cookbook']});
}, 1500);
})
}
const getDesignation = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve({designation: 'Software Architect'});
}, 1500);
})
}
const getUser = () => {
return new Promise(resolve => {
setTimeout(() => {
resolve({user: 'Sudongyuer'});
}, 1500);
})
}
const performTasks = async () => {
const {user} = await getUser();
console.log('user retrieved', user);
const {designation} = await getDesignation();
console.log('designation retrieved', designation);
const {books} = await getBooks();
console.log('books retrieved', books);
const {socials} = await getSocials();
console.log('socials retrieved', socials);
}
請注意,我們將代碼包裝在performTasks()函數(shù)中,這是一個async函數(shù),您可以看到async關鍵字的用法。在內部,我們使用await關鍵字進行每個函數(shù)調用,這基本上會在執(zhí)行下一行代碼之前等待函數(shù)的承諾得到解決。使用這種語法,我們的代碼看起來好像都是同步的,但實際上是異步的。而且我們的代碼更干凈!
新聞標題:八種技巧讓你編寫更簡潔的JavaScript代碼
文章起源:http://m.fisionsoft.com.cn/article/dpedppd.html


咨詢
建站咨詢
