javascript 的 this 指向主要是依賴上下文對象決定,箭頭函數例外。javascript
在全局做用域下調用函數,函數的this
默認指向window
。java
注意1:嚴格模式下,默認指向undefined
app
function test() { console.log(this.a); } var a = 1; test(); // 1 // 嚴格模式 function test() { 'use strict'; console.log(this.a); } var a = 1; test(); // TypeEror 報錯
注意2:全局做用域下 var
聲明的變量會默認綁定到window
,而let
、const
聲明的變量不會函數
let a = 1; var b = 1; window.a // undefined window.b // 1
當函數引用有上下文對象時,this
隱式綁定到這個上下文對象中。this
function test() { console.log(this.a); } var obj = { a: 1, test: test } var a = 2; obj.test(); // 1
隱式丟失prototype
function test() { console.log(this.a); } var obj = { a: 1, test: test } var a = 2; // 隱式丟失,this 應用默認綁定規則 var bar = obj.test; bar() // 2
call
、apply
、bind
等顯式改變this
指向。code
注意:非嚴格模式下,call
、apply
、bind
等傳入null
、undefined
會默認轉爲window
對象
function test() { console.log(this.a); } var obj = { a: 1 } var a = 2; test(); // 2 test.call(obj); // 1 test.apply(obj); // 1 var bTest = test.bind(obj); bTest(); // 1
注意2:屢次使用bind
,this
只會指向第一次bind
的this
ip
function test() { console.log(this.a); } var obj1 = { a: 1 } var obj2 = { a: 2 } var obj3 = { a: 3 } var bind1 = test.bind(obj1); bind1(); // 1 var bind2 = bind1.bind(obj2); bind2(); // 1 var bind3 = bind2.bind(obj3); bind3(); // 1
內置函數改變this
指向作用域
function test() { console.log(this.a); } var obj = { a: 1 } var arr = [1, 2, 3]; arr.forEach(test, obj); // 打印 3 個 1
使用new
操做符會產生以下步驟:
prototype
相連。this
。function create() { let obj = new Object(); let constructor = [].shift.call(arguments); // obj.__proto__ = constructor.prototype; Object.setPrototypeOf(obj, constructor.prototype); // 改變 this let res = constructor.apply(obj, arguments); const isObj = Object.prototype.toString.call(res) === '[object Object]'; return isObj ? result : obj; }
箭頭函數比較特殊,它有如下幾個特色:
沒有自身的this
,在定義時默認綁定父級做用域的this
,即採用詞法做用域綁定this
.
沒有原型 prototype
,沒法使用 new 操做符,即不能做爲構造函數.
沒法使用call
、apply
、bind
等顯式改變其this
.
const test = () => console.log(this); let obj = {}; test(); // window test.call(obj); // window const foo = test.bind(obj); foo(); // window