** 聲明 **:本文只是在本人學(xué)習(xí)時(shí)得到的一些知識针姿,如果發(fā)現(xiàn)問題可以與我聯(lián)系袱吆,內(nèi)容有不實(shí)之處請見諒。
一距淫、前言
在ES3的版本(就是那種1000個(gè)人寫出999種版本的....哈哈哈)绞绒,第一次見到j(luò)s的時(shí)候我很激動,握草什么榕暇!怎么能有這么靈活的語法~~~java簡直是個(gè)渣渣老是和裹腳布一樣辣么長蓬衡,但是.....凡事有利就有弊,比如說下面這段代碼
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 這個(gè)等于6哦
機(jī)智的你肯定發(fā)現(xiàn)問題了吧彤枢!其實(shí)等于的是10狰晚,嘖嘖!為什么嘞~(大神們繞道->_->)
??因?yàn)檫@個(gè)
i
被莫名提拔成為了全局變量,所以i
的值一直在被覆蓋產(chǎn)生了泄露??在ES3中只有var類型的時(shí)候非常的方便,不要管什么變量直接扔就行
但是C泵ァ!讨衣!但是;慌铩!反镇!重點(diǎn)來了固蚤,js中使用var會出現(xiàn)變量等級提升的特性,用例子來說就是
console.log(a); // 輸出 undefined
var a = 1;
明白了不歹茶?啊~~不明白夕玩?就是說js在使用var時(shí)不管它出現(xiàn)在那個(gè)位置都會放到最前面進(jìn)行聲明就像是關(guān)系戶總會比我們快一點(diǎn),上面的例子可以這么看
var a; // 嘿嘿惊豺,人家可是var燎孟,有特權(quán)
console.log(a); // 輸出 undefined
a = 1;
ok!我們都很痛恨這種不按規(guī)矩辦事的人尸昧,所以清官~哦揩页,不!是let
變量出來了
二烹俗、let
let
這位清官非常守自己的本分除了在本身塊級作用域里面能找得到它爆侣,在外面更本找不到!嗯....確實(shí)和清官挺像的幢妄,來個(gè)代碼吧
{
console.log(a); // 報(bào)錯(cuò) ReferenceError |T_T我是清官沒特權(quán)
let a = 10;
var b = 1;
}
a // ReferenceError: a is not defined. |T_T外面果然都不知道我
b // 1
既然是清官眼里也是揉不得沙子
var a = 123;
function guanxihu(a){ // ReferenceError | var a:我擦我被拒絕入境了
a = 'abc'; // ReferenceError
let a;
}
這其實(shí)是TDZ(暫時(shí)性死區(qū))也就是說在let
這個(gè)清官會把外界的惡勢力擋住兔仰,并且自己也不會插隊(duì)。也就是說在塊級作用域中當(dāng)存在let
變量聲明的時(shí)候蕉鸳,前面不允許出現(xiàn)相應(yīng)變量
{
// TDZ 開始
a = 'abc'; // ReferenceError
console.log(a); // ReferenceError
let a; // TDZ 結(jié)束
console.log(a); // undefined
a = 123;
console.log(a); // 123
}
總結(jié)就是進(jìn)入當(dāng)前作用域時(shí)相應(yīng)變量已經(jīng)存在但是不可獲取乎赴,只有當(dāng)出現(xiàn)相應(yīng)的變量聲明后才會解除鎖定
??那你說我讓清官干完活再換關(guān)系戶就好了,比如這樣
{
let a = 1;
...........(不可描述的事情)
var a = 2;
}
不好意思這會產(chǎn)生錯(cuò)誤
Identifier 'tmp' has already been declared
也就是這個(gè)位置已經(jīng)占了~~(畢竟上級覺得這個(gè)人做的很不錯(cuò)啊置吓,換了人我的業(yè)績過不去了怎么辦)
??相對的上級也怕出現(xiàn)兩個(gè)清官就會鬧出很多事无虚,所以下面這樣也是不行
{
let a = 1;
let a = 2; // ReferenceError
}
好處
嘖嘖還記得第一次看到匿名自執(zhí)行函數(shù)(IIFE)的時(shí)候覺得這個(gè)牛逼啊缔赠,也不會污染變量想出這個(gè)的肯定是神人
(function () {
var a = ...;
...
}());
但是這個(gè)終歸是技巧衍锚,當(dāng)我們有了let
之后
{
let a = ...;
...
}
干凈!簡單嗤堰!符合人的思維戴质!T*D怎么才出來這個(gè)(更多的妙用可以自行體會,核心的原理都是上面說的那些)
注意
由于ES5規(guī)定函數(shù)不能在塊級作用域申明(瀏覽器不報(bào)錯(cuò)會將函數(shù)設(shè)置成var在塊級函數(shù)的表現(xiàn))踢匣,但是ES6又引入了告匠,不過這讓瀏覽器小弟們非常為難。比如
function f() { console.log('1'); }
(function () {
if (false) {
// 重復(fù)聲明一次函數(shù) f
function f() { console.log('2'); }
}
f();
}());
在ES5中是這樣的
function f() { console.log('1'); }
(function () {
function f() { console.log('2'); }
if (false) {}
f(); // 2
}());
在ES6中是這樣的
function f() { console.log('1'); }
(function () {
f(); // 1
}());
所以在塊級作用域當(dāng)中申明函數(shù)使用如下函數(shù)表達(dá)式而非聲明式
let a = 'secret';
let f = function () {
return a;
};
注:ES6中聲明塊級作用域函數(shù)相當(dāng)于聲明了
let
离唬,不過具體需要看瀏覽器的解析
三后专、const
const
像是一個(gè)占有欲非常強(qiáng)烈的人,它一旦被聲明同時(shí)必須賦值输莺,而且以后不能改變
const PI = 3.1415;
PI // 3.1415
PI = 3; // TypeError: Assignment to constant variable.
const HU;// SyntaxError: Missing initializer in const declaration
但是他還是有底線的哦~只占有自己的東西這與let
一樣都是在塊級作用域中有效并且也是存在TDZ戚哎,深入的講就是每個(gè)const
聲明的變量都指向一個(gè)地址裸诽,這個(gè)地址是不能被改變的,但是里面存儲的東西是可以進(jìn)行替換的
const a= {};
a.prop = 123;
console.log(a.prop) // 123
a= {}; // TypeError: "foo" is read-only
四型凳、歷史遺留的全局屬性
在發(fā)展中留下了許多暗傷比如一直引發(fā)很多問題的
window.a = 1;
a // 1
a = 2;
window.a // 2
全局對象的屬性賦值與全局變量的賦值丈冬,是同一件事,這會引發(fā)很多原本不應(yīng)該存在的問題甘畅,所以這種塊級作用域的變量出現(xiàn)了埂蕊!
var a = 1;
window.a // 1
let b = 1;
window.b // undefined
五、結(jié)語
哈哈哈~~平常話講的少只能在這種時(shí)候扯一點(diǎn)疏唾,內(nèi)容有誤的地方還請大家指出蓄氧,有很多廢話也請大家見諒,晚安槐脏!