變數let、const
ES5 中,使用 var 定義變數( var 是 variable 的簡寫),
ES6 中,新增了 let 和 const 來定義變數:
-
let:定義變數,替代 var, -
const:定義常量(定義后,不可修改),
1、let:定義變數
舉例 1:
{
let a = 'hello';
}
console.log(a); // 列印結果報錯:Uncaught ReferenceError: a is not defined
上方代碼,列印報錯,
舉例 2:
var a = 2;
{
let a = 3;
}
console.log(a); // 列印結果:2
通過上面兩個例子可以看出,用塊級作用域內, 用let 宣告的變數,只在區域起作用,
經典面試題:
let 可以防止資料污染,我們來看下面這個 for 回圈的經典面試題,
1、用 var 宣告變數:
for (var i = 0; i < 10; i++) {
console.log('回圈體中:' + i);
}
console.log('回圈體外:' + i);
上方代碼的最后一行可以正常列印結果,且最后一行的列印結果是 10,說明回圈體外定義的變數 i,是全域作用域下的 i,
2、用 let 宣告變數:
for (let i = 0; i < 10; i++) {
console.log('回圈體中:' + i); // // 每回圈一次,就會在 { } 所在的塊級作用域中,重新定義一個新的變數 i
}
console.log('回圈體外:' + i);
上方代碼的關鍵在于:每次回圈都會產生一個塊級作用域,每個塊級作用域中會重新定義一個新的變數 i,
另外,上方代碼的最后一行,列印會報錯,因為用 let 定義的變數 i,只在{ }這個塊級作用域里生效,
總結:我們要習慣用 let 宣告,減少 var 宣告帶來的污染全域空間,
為了進一步強調 let 不會帶來污染,需要說明的是:當我們定義了let a = 1時,如果我們在同一個作用域內繼續定義let a = 2,是會報錯的,
2、const:定義常量
在程式開發中,有些變數是希望宣告后,在業務層就不再發生變化,此時可以用 const 來定義常量,常量就是值(記憶體地址)不能變化的量,
舉例:
const name = 'smyhvae'; //定義常量
用 const 宣告的常量,只在區域(塊級作用域內)起作用;而且,用 const 宣告常量時,必須賦值,否則報錯,
let 和 const 的特點【重要】
-
不屬于頂層物件 Window
-
不允許重復宣告
-
不存在變數提升 必須先定義后使用
-
暫時性死區 當內部變數與外部你變數同名時,內部變數屏蔽外部變數
-
支持塊級作用域 該變數在該作用域不會消失
相反, 用var宣告的變數:存在變數提升、可以重復宣告、沒有塊級作用域,
var/let/const 的共同點
-
全域作用域中定義的變數,可以在函式中使用,
-
函式中宣告的變數,只能在函式及其子函式中使用,外部無法使用,
this 指向
this:是函式體內的內置物件(this只能出現在函式體內)
1、以函式的形式(包括普通函式、定時器函式、立即執行函式)呼叫時,this 的指向永遠都是 window,比如fun();相當于window.fun();
2、以方法的形式呼叫時,this 指向呼叫方法的那個物件
3、以建構式的形式呼叫時,this 指向實體物件
4、以事件系結函式的形式呼叫時,this 指向系結事件的物件
5、使用 call 和 apply 呼叫時,this 指向指定的那個物件
第 1 條的舉例:
function fun() {
console.log(this);
console.log(this.name);
}
var obj1 = {
name: 'smyh',
sayName: fun,
};
var obj2 = {
name: 'vae',
sayName: fun,
};
var name = '全域的name屬性';
//以函式形式呼叫,this是window
fun(); //可以理解成 window.fun()
列印結果:
Window
全域的name屬性
上面的舉例可以看出,this 指向的是 window 物件,所以 this.name 指的是全域的 name,
第 2 條的舉例:
function fun() {
console.log(this);
console.log(this.name);
}
var obj1 = {
name: 'smyh',
sayName: fun,
};
var obj2 = {
name: 'vae',
sayName: fun,
};
var name = '全域的name屬性';
//以方法的形式呼叫,this是呼叫方法的物件
obj2.sayName();
列印結果:
Object
vae
上面的舉例可以看出,this 指向的是 物件 obj2 ,所以 this.name 指的是 obj2.name,
ES6 箭頭函式中 this 的指向
ES6 中的箭頭函式并不使用上面的準則,而是會繼承外層函式呼叫的 this 系結(無論 this 系結到什么),
bind() 方法
bind() 方法的作用
bind() 方法不會呼叫函式,但是可以改變函式內部的 this 指向,
把call()、apply()、bind()這三個方法做一下對比,你會發現:實際開發中, bind() 方法使用得最為頻繁,如果有些函式,我們不需要立即呼叫,但是又想改變這個函式內部的this指向,此時用 bind() 是最為合適的,
語法:
新函式 = fn1.bind(想要將this指向哪里, 函式實參1, 函式實參2);
引數:
-
第一個引數:在 fn1 函式運行時,指定 fn1 函式的this 指向,如果不需要改變 this 指向,則傳 null,
-
其他引數:fn1 函式的實參,
解釋:它不會呼叫 fn1 函式,但會回傳 由指定this 和指定實參的原函式拷貝,可以看出, bind() 方法是有回傳值的,
箭頭函式
定義箭頭函式的語法
語法:
(引數1, 引數2 ...) => { 函式體 }
解釋:
-
如果有且僅有 1 個形參,則
()可以省略 -
如果函式體內有且僅有 1 條陳述句,則
{}可以省略,但前提是,這條陳述句必須是 return 陳述句,舉例
寫法 1、定義和呼叫函式:(傳統寫法)
function fn1(a, b) { console.log('haha'); return a + b; } console.log(fn1(1, 2)); //輸出結果:3寫法 2、定義和呼叫函式:(ES6 中的寫法)
const fn2 = (a, b) => { console.log('haha'); return a + b; }; console.log(fn2(1, 2)); //輸出結果:3上面的兩種寫法,效果是一樣的,
從上面的箭頭函式中,我們可以很清晰地看到變數名、引數名、函式體,
【重要】在箭頭函式中,如果方法體內只有一句話,且這句話是 return 陳述句,那就可以把
{}省略,寫法如下:const fn2 = (a, b) => a + b; console.log(fn2(1, 2)); //輸出結果:3在箭頭函式中,如果形參只有一個引數,則可以把
()省略,寫法如下:const fn2 = (a) => { console.log('haha'); return a + 1; }; console.log(fn2(1)); //輸出結果:2箭頭函式的 this 的指向
ES6 之前的普通函式中:this 指向的是函式被呼叫的物件(也就是說,誰呼叫了函式,this 就指向誰),
而 ES6 的箭頭函式中:箭頭函式本身不系結 this,this 指向的是箭頭函式定義位置的 this(也就是說,箭頭函式在哪個位置定義的,this 就跟這個位置的 this 指向相同),
const obj = { name: '123' }; function fn1() { console.log(this); // 第一個 this return () => { console.log(this); // 第二個 this }; } const fn2 = fn1.call(obj); fn2();列印結果:
obj obj代碼解釋:
上面的代碼中,箭頭函式是在 fn1()函式里面定義的,所以第二個 this 跟 第一個 this 指向的是同一個位置,又因為,在執行
fn1.call(obj)之后,第一個 this 就指向了 obj,所以第二個 this 也是指向 了 obj,
變數的解構賦值
解構賦值:ES6 允許我們,按照一一對應的方式,從陣列或者物件中提取值,再將提取出來的值賦值給變數,
解構:分解資料結構;賦值:給變數賦值,
解構賦值在實際開發中可以大量減少我們的代碼量,并且讓程式結構更清晰,
陣列的解構賦值
陣列的結構賦值:將陣列中的值按照位置提取出來,然后賦值給變數,
語法
在 ES6 之前,當我們在為一組變數賦值時,一般是這樣寫:
var a = 1;
var b = 2;
var c = 3;
或者是這樣寫:
var arr = [1, 2, 3];
var a = arr[0];
var b = arr[1];
var c = arr[2];
現在有了 ES6 之后,我們可以通過陣列解構的方式進行賦值:(根據位置進行一一對應)
let [a, b, c] = [1, 2, 3];
二者的效果是一樣的,但明顯后者的代碼更簡潔優雅,
物件的解構賦值
物件的結構賦值:將物件中的值按照屬性匹配的方式提取出來,然后賦值給變數,
語法
在 ES6 之前,我們從介面拿到 json 資料后,一般這么賦值:
var name = json.name;
var age = json.age;
var sex = json.sex;
上面這種寫法,過于麻煩了,
現在,有了 ES6 之后,我們可以使用物件解構的方式進行賦值,舉例如下:
const person = { name: 'qianfan', age: 25, sex: '男' };
let { name, age, sex } = person; // 物件的結構賦值
console.log(name); // 列印結果:qianguyihao
console.log(age); // 列印結果:28
console.log(sex); // 列印結果:男
上方代碼可以看出,物件的解構與陣列的結構,有一個重要的區別:陣列的元素是按次序排列的,變數的取值由它的位置決定;而物件的屬性沒有次序,是根據鍵來取值的,
圓括號的使用
如果變數 foo 在解構之前就已經定義了,此時你再去解構,就會出現問題,下面是錯誤的代碼,編譯會報錯:
let foo = 'haha';
{ foo } = { foo: 'smyhvae' };
console.log(foo);
要解決報錯,只要在解構的陳述句外邊,加一個圓括號即可:
let foo = 'haha';
({ foo } = { foo: 'smyhvae' });
console.log(foo); //輸出結果:smyhvae
字串解構
字串也可以解構,這是因為,此時字串被轉換成了一個類似陣列的物件,舉例如下:
const [a, b, c, d] = 'hello';
console.log(a);
console.log(b);
console.log(c);
console.log(typeof a); //輸出結果:string
列印結果:
h
e
l
string
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/538478.html
標籤:其他
上一篇:web系統添加盲水印
