說明
每天10分鐘,重構你的前端知識體系專欄筆記。
一、函數
1.1、普通函數
用 function
關鍵字定義的函數。
function kaimo(){
// code
}
1.2、箭頭函數
用 =>
運算符定義的函數。
const kaimo = () => {
// code
}
1.3、方法
在 class
中定義的函數。
class KK {
kaimo(){
//code
}
}
1.4、生成器函數
用 定義的函數。這種聲明方式會定義一個生成器函數 (generator function),它傳回一個
function*
對象。
Generator
function* kaimo(){
// code
}
1.5、類
用 class
定義的類,實際上也是函數。
class KK {
constructor(){
//code
}
}
1.6、異步函數
普通函數、箭頭函數和生成器函數加上 async 關鍵字。
async function kaimo(){
// code
}
const kaimo = async () => {
// code
}
async function kaimo*(){
// code
}
二、this關鍵字
是執行上下文中很重要的一個組成部分。同一個函數調用方式不同,得到的
this
值也不
this
2.1、普通函數情況下
function showThis(){
console.log(this);
}
var o = {
showThis: showThis
}
showThis(); // global
o.showThis(); // o
普通函數的 值由
this
決定。擷取函數的表達式,傳回的是一個
調用它所使用的引用
類型。
Reference
類型由兩部分組成:一個對象和一個屬性值。
Reference
上面代碼裡
o.showThis
産生的
Reference
類型,即由對象
o
和屬性
showThis
構成。
調用函數時使用的引用,決定了函數執行時刻的
this
值。
2.2、箭頭函數情況下
const showThis = () => {
console.log(this);
}
var o = {
showThis: showThis
}
showThis(); // global
o.showThis(); // global
改為箭頭函數後,不論用什麼引用來調用它,都不影響它的
this
值。
2.3、方法情況下
// 這一個沒怎麼弄明白,mark一下
class C {
showThis() {
console.log(this);
}
}
var o = new C();
var showThis = o.showThis;
showThis(); // undefined
o.showThis(); // o
首先建立了一個類
C
,并且執行個體化出對象
o
,再把
o
的方法指派給了變量
showThis
。
三、this 關鍵字的機制
1、在
JavaScript
标準中,為函數規定了用來儲存定義時上下文的私有屬性
[[Environment]]
。
2、當一個函數執行時,會建立一條新的執行環境記錄,記錄的外層詞法環境(
outer lexical environment
)會被設定成函數的
[[Environment]]
。
/* 執行上下文的切換機制 */
var a = 1;
foo();
// 在别處定義了 foo:
var b = 2;
function foo(){
console.log(b); // 2
console.log(a); // error
}
foo
能夠通路
b
(定義時詞法環境),卻不能通路
a
(執行時的詞法環境)
3、
JavaScript
用一個
棧
來管理執行上下文,這個棧中的每一項又包含一個連結清單。
當函數調用時,會入棧一個新的執行上下文,函數調用結束時,執行上下文被出棧。
4、
[[thisMode]]
私有屬性。
-
:表示從上下文中找lexical
,這對應了箭頭函數。this
-
:表示當global
為this
時,取全局對象,對應了普通函數。undefined
-
:當嚴格模式時使用,strict
嚴格按照調用時傳入的值,可能為this
或者null
。undefined
"use strict"
function showThis(){
console.log(this);
}
var o = {
showThis: showThis
}
showThis(); // undefined
o.showThis(); // o
四、操作 this 的内置函數
function foo(a, b, c){
console.log(this);
console.log(a, b, c);
}
//call 和 apply 作用一樣,隻是傳參方式有差別
foo.call({}, 1, 2, 3); // {} 1 2 3
foo.apply({}, [1, 2, 3]); // {} 1 2 3
function foo(a, b, c){
console.log(this);
console.log(a, b, c);
}
foo.bind({}, 1, 2, 3)(); // {} 1 2 3