同步發表於微信公衆號:前端微志前端
在上次的 「Chrome DevTools 你可能不知道的小技巧」 文中,獲得不少開發朋友的反饋確實不知道這些小技巧。今天,咱們來聊一聊在 EcmaScript 5/6+
中的一些小技巧,歡迎評論區討論下更多技巧。面試
咱們平時常常會用到 JSON
對象,好比當咱們要實現對象的深拷貝時,咱們能夠用 JSON
對象的 JSON.stringify
和 JSON.parse
來拷貝一個徹底同樣的對象,而不會對原對象產生任何引用關係。在使用 localStorage
時,也會用到它,由於 localStorage
只能存儲字符串格式的內容,因此,咱們在存以前,將數值轉換成 JSON字符串
,取出來用的時候,再轉成對象或數組。json
對於 JSON.stringify
方法,它能夠幫咱們把一個對象或數組轉換成一個 JSON字符串
。咱們一般只會用到它的第一個參數,其實它還有另外兩個參數,可讓它實現一些很是好用的功能。數組
首先來看語法:微信
JSON.stringify(value[, replacer [, space]])
參數:markdown
value
每一個屬性都要通過這個函數的處理,該函數的返回值就是最後被序列化後的值。若是是一個數組,則要求該數組的元素是字符串,且這些元素會被當作 value
的鍵(key
)進行匹配,最後序列化的結果,是隻包含該數組每一個元素爲 key
的值。這時候,你應該知道了。咱們能夠用 JSON.stringify
來作序列化時的過濾,至關於咱們能夠自定義 JSON.stringify
的解析邏輯。數據結構
使用函數過濾並序列化對象:app
// 使用「函數」當替代器
function replacer(key, value) {
if (typeof value === "string") {
return undefined;
}
return value;
}
var foo = {
foundation: "Mozilla",
model: "box",
week: 45,
transport: "car",
month: 7
};
var jsonString = JSON.stringify(foo, replacer);
// {"week":45,"month":7}
複製代碼
使用數組過濾並序列化對象:函數
// 使用「數組」當替代器
const user = {
name: 'zollero',
nick: 'z',
skills: ['JavaScript', 'CSS', 'HTML5']
};
JSON.stringify(user, ['name', 'skills'], 2);
// "{
// "name": "zollero",
// "skills": [
// "JavaScript",
// "CSS",
// "HTML5"
// ]
// }"
複製代碼
還有一個有意思的東西,是對象的 toJSON
屬性。oop
若是一個對象有 toJSON
屬性,當它被序列化的時候,不會對該對象進行序列化,而是將它的toJSON
方法的返回值進行序列化。
見下面的例子:
var obj = {
foo: 'foo',
toJSON: function () {
return 'bar';
}
};
JSON.stringify(obj); // '"bar"'
JSON.stringify({x: obj}); // '{"x":"bar"}'
複製代碼
在 ES6
中,引入了一個新的數據結構類型:Set
。而 Set
與 Array
的結構是很相似的,且 Set
和 Array
能夠相互進行轉換。
數組去重,也算是一個比較常見的前端面試題了,方法有不少種,這裏很少贅述。下面咱們看看用 Set
和 ...(拓展運算符)
能夠很簡單的進行數組去重。
const removeDuplicateItems = arr => [...new Set(arr)];
removeDuplicateItems([42, 'foo', 42, 'foo', true, true]);
//=> [42, "foo", true]
複製代碼
在開發的過程當中,一般會遇到命名衝突的問題,就是須要根據場景不一樣來定義不一樣的值來賦值給同一個變量。下面介紹一個使用 ES6
中的 塊級做用域
來解決這個問題的方法。
好比,在使用 switch case
時,咱們能夠這樣作:
switch (record.type) {
case 'added': {
const li = document.createElement('li');
li.textContent = record.name;
li.id = record.id;
fragment.appendChild(li);
break;
}
case 'modified': {
const li = document.getElementById(record.id);
li.textContent = record.name;
break;
}
}
複製代碼
咱們知道,在 ES6
中,爲函數增長了參數默認值的特性,能夠爲參數設定一些默認值,可讓代碼更簡潔,可維護。
其實,咱們能夠經過這個特性來作函數參數值的校驗。
首先,函數的參數能夠是任意類型的值,也能夠是函數,好比下面這個:
function fix(a = getA()) {
console.log('a', a)
}
function getA() {
console.log('get a')
return 2
}
fix(1);
// a 1
fix();
// get a
// a 2
複製代碼
能夠看出,若是在調用 fix
時傳了參數 a
,則不會執行函數 getA
,只有當不傳遞參數 a
時,纔會執行函數 getA
。
這時候,咱們能夠利用這一特性,爲參數 a
添加一個必傳的校驗,代碼以下:
function fix(a = require()) {
console.log('a', a)
}
function require() {
throw new Error('缺乏了參數 a')
}
fix(1);
// a 1
fix();
// Uncaught Error: 缺乏了參數 a
複製代碼
在前面咱們介紹了使用 JSON.stringify
來過濾對象的屬性的方法。這裏,咱們介紹另一種使用 ES6
中的 解構賦值
和 拓展運算符
的特性來過濾屬性的方法。
好比,下面這段示例:
// 咱們想過濾掉對象 types 中的 inner 和 outer 屬性
const { inner, outer, ...restProps } = {
inner: 'This is inner',
outer: 'This is outer',
v1: '1',
v2: '2',
v4: '3'
};
console.log(restProps);
// {v1: "1", v2: "2", v4: "3"}
複製代碼
解構賦值
的特性很強大,它能夠幫咱們從一堆嵌套很深的對象屬性中,很方便地拿到咱們想要的那一個。好比下面這段代碼:
// 經過解構賦值獲取嵌套對象的值
const car = {
model: 'bmw 2018',
engine: {
v6: true,
turbo: true,
vin: 12345
}
};
// 這裏使用 ES6 中的簡單寫法,使用 { vin } 替代 { vin: vin }
const modalAndVIN = ({ model, engine: { vin }}) => {
console.log(`model: ${model}, vin: ${vin}`);
}
modalAndVIN(car);
// "model: bmw 2018, vin: 12345"
複製代碼
合併對象
ES6
中新增的 拓展運算符
,能夠用來解構數組,也能夠用來解構對象,它能夠將對象中的全部屬性展開。
經過這個特性,咱們能夠作一些對象合併的操做,以下:
// 使用拓展運算符合並對象,在後面的屬性會重寫前面相同屬性的值
const obj1 = { a: 1, b: 2, c: 3 };
const obj2 = { c: 5, d: 9 };
const merged = { ...obj1, ...obj2 };
console.log(merged);
// {a: 1, b: 2, c: 5, d: 9}
const obj3 = { a: 1, b: 2 };
const obj4 = { c: 3, d: { e: 4, ...obj3 } };
console.log(obj4);
// {c: 3, d: {a: 1, b: 2, e: 4} }
複製代碼
使用 === 代替 ==
在 JavaScript
中,===
和 ==
是有很大的不一樣的,==
會將兩邊的變量進行轉義,而後將轉義後的值進行比較,而 ===
是嚴格比較,要求兩邊的變量不只值要相同,它們自身的類型也要相同。
JavaScript
常常被調侃成一個神奇的語言,就是由於它的轉義的特性,而用 ==
可能會引入一些深埋的bug。遠離 bug,仍是要用 ===
:
[10] == 10 // true
[10] === 10 // false
'10' == 10 // true
'10' === 10 // false
[] == 0 // true
[] === 0 // false
'' == false // true
'' === false // false
複製代碼
固然,在用 ===
時,也會出問題,好比:
NaN === NaN // false
複製代碼
ES6
中提供了一個新的方法:Object.is()
,它具備 ===
的一些特色,並且更好、更準確,在一些特殊場景下變現的更好:
Object.is(0 , ' '); //false
Object.is(null, undefined); //false
Object.is([1], true); //false
Object.is(NaN, NaN); //true
複製代碼
下圖,是關於 ==
、===
和 Object.is
的對比:
引用: