Javascript是一門很靈活的語言,我們可以使用它動(dòng)態(tài)地實(shí)現(xiàn)各種各樣的功能。但是動(dòng)態(tài)帶來便利的同時(shí),也存在一些令人費(fèi)解的行為,稍不注意就會(huì)進(jìn)入誤區(qū)一個(gè)接著一個(gè)的坑。雖然我使用JavaScript的時(shí)間還不算長,也是遇到了一些有意思的場景,一開始百思不得其解,弄清楚之后又讓我哭笑不得。現(xiàn)在就來跟大家一起分享一下。
語法糖帶來的淺拷貝
先來預(yù)測一下下面代碼的輸出內(nèi)容:
const user = {
name: 'zong',
location: {
city: 'Shanghai',
state: 'Shanghai'
}
};
const copy = Object.assign({}, user);
// 或者
// const copy = { ...user };
copy.location.city = 'Suzhou';
console.log('original: ', user.location);
console.log('copy:', copy.location);
輸出結(jié)果應(yīng)該是:
original: {
city: 'Shanghai',
state: 'Shanghai'
}
copy: {
city: 'Shanghai',
state: 'Shanghai'
}
咦?為什么操作復(fù)制的對(duì)象會(huì)修改原來的對(duì)象呢?這是因?yàn)?code>Object.assign跟spread operator只做了一層淺拷貝,這意味著只有對(duì)象的第一層屬性會(huì)被復(fù)制,如果某個(gè)屬性是個(gè)嵌套的對(duì)象,那么只有引用會(huì)被復(fù)制,所以我們操作修改的對(duì)象的屬性影響到了原來的對(duì)象。
所以在我們這個(gè)例子中copy的location屬性將仍然指向原來user對(duì)象對(duì)應(yīng)的location屬性。
JavaScript從右向左賦值的行為
function display() {
var a = b = 10;
}
display();
console.log('b', typeof b === 'undefined');
console.log('a', typeof a === 'undefined');
輸出是:
b false
a true
這是因?yàn)镴avaScript賦值操作符是從右向左的,這意味著我們的賦值操作也是從右向左來的,手先b會(huì)被賦值10,然后它被賦給了a。
所以:
function display() {
var a = b = 10;
}
等同于:
function display() {
b = 10;
var a = b;
}
所以b沒有用var聲明成了一個(gè)全局變量,所以在外部可以被訪問到,而a只是個(gè)局部變量,所以外部會(huì)打印出a === undefined為true。

但是如果上面的代碼在嚴(yán)格模式中執(zhí)行的話,情況又不一樣了,由于嚴(yán)格模式不允許創(chuàng)建全局變量所以這段代碼會(huì)直接拋出異常。
提升
var num = 8;
var display = function () {
console.log(num);
var number = 20;
};
display();
猜猜這里的輸出結(jié)果是什么?它不是8而是undefined,這又是為什么?
這是因?yàn)镴avaScript里面有個(gè)現(xiàn)象叫提升。提升是JavaScript中把變量聲明移到當(dāng)前作用域最頂部的一種行為。
所以上面的代碼可以轉(zhuǎn)換成如下:
var num = 8;
var display = function () {
var num;
console.log(num);
num = 20;
};
display();
我們可以看到只有聲明被移到了函數(shù)的最頂端,而賦值操作還在原地,所以這邊num由于還未賦值會(huì)打印出undefined。
delete的作用對(duì)象
const num = 1;
const result = (function () {
delete num;
return num;
})();
console.log(result);
這邊的代碼不會(huì)報(bào)出任何錯(cuò),因?yàn)槲覀兪窃?code>number類型上使用的delete,它還是會(huì)打印出1。
The delete操作符被用來刪除一個(gè)對(duì)象的屬性,在這兒num并不是一個(gè)對(duì)象所以它會(huì)返回這個(gè)變量對(duì)應(yīng)的值,也就是1。
const num = 1;
const result = (function (num) {
delete num;
return num;
})(10);
console.log(result);
上面的代碼將輸出10。
這邊我們把10作為參數(shù)傳給函數(shù),同樣地delete在這里對(duì)原始類型也不起作用,所以會(huì)照常打印出10。
好啦,今天的分享就到這里啦,主要是在使用JavaScript的過程中可能會(huì)經(jīng)常遇到的一些細(xì)節(jié)問題,希望能給大家?guī)硪粊G丟的收獲,happy coding~