本文最最核心的一句話就是:
this
是在函數調用的時候确定的,一定要牢牢記住,其次,在函數執行過程中,
this
一旦被确定,就不可更改了。
var a = 10;
var obj = {
a: 20
}
function fn(){
this= obj; // 這句話試圖修改this,運作後會報錯
console.log(this.a);
}
fn();
this
是什麼
this
重點:
this
是一個對象,是對象和函數之間達成關聯關系的紐帶,是在函數調用的時候确定。
怎麼确定 this
的指向
this
因為
this
是在函數調用的時候确定的,是以
this
的指向是很靈活的,是以很多人對
this
的指向總是似懂非懂。那麼這裡可以告訴大家一個套路,也是本文唯一的套路,按照這個套路走,以後
this
的問題再也難不倒你了。
當你不能确定
this
指向哪裡的時候,嘗試把函數的調用轉換為
call/apply
的形式,
call/apply
的第一個參數就是
this
的指向!
call/apply
手動指定 this
call/apply
this
call/apply
可以自行手動設定
this
的指向。所有的函數都具有着兩個方法,它們除了參數略有不同,其功能完全一樣。它們的第一個參數都為
this
将要指向的對象。
call/apply
的具體使用這裡就不講了,如果不熟悉
call/apply
的用法 送你傳送門
function fn(param) {
console.log(this.a,param);
}
var obj = {
a: "我是this的屬性a"
}
fn.call(obj,"我是參數param"); // 我是this的屬性a 我是參數param
-
第一個參數如果傳入的是簡單資料類型,會被自動包裝為對象call/apply
function f(){ console.log(this) } f.call(10); // Number {10} f.call(true); // Boolean {true} f.call("str"); // String {"str"}
-
第一個參數如果沒傳,或者傳入的是call/apply
的時候,null/undefined
的指向跟是否在嚴格模式下有關。this
- 非嚴格模式下,
指向全局對象(浏覽器是this
)。window
function f(){ console.log(this) } f.call(); // Window {postMessage: ƒ,...} f.call(null); // Window {postMessage: ƒ,...} f.call(undefined); // Window {postMessage: ƒ,...}
- 嚴格模式下,
指向this
null/undefined
"use strict" function f(){ console.log(this) } f.call(); // undefined f.call(null); // null f.call(undefined); // undefined
- 非嚴格模式下,
幾個栗子
隻要掌握
call/apply
,結合是否嚴格模式,你就會發現虛無缥缈的
this
已經有迹可循了,下面例子中的函數調用代碼都可以通過轉換的
call
模式代碼直接替換。
- 純粹的函數調用
// 非嚴格模式 var x = 1; function test() { console.log(this.x); } // 在心裡将test()翻譯為call模式,test.call(),非嚴格模式 // 是以this===window,是以輸出window.x test(); // 1 // 嚴格模式 "use strict" var x = 1; function test() { console.log(this.x); } // 在心裡将test()翻譯為call模式,test.call(),嚴格模式 // 是以this===undefined,是以輸出window.x test(); // Uncaught TypeError: Cannot read property 'x' of undefined
- 作為對象方法的調用
function test() { console.log(this.x); } var obj = { x:3, m:test }; // 在心裡将test()翻譯為call模式,obj.m.call(obj),這時this===obj,是以輸出obj.x obj.m(); // 3
- 作為構造函數調用,
就指向構造出來的新對象this
function Test() { this.x = 3; } // 在心裡将test()翻譯為call模式 // var obj = {}; Test.call(obj); // 這時this===obj,是以輸出obj.x var obj = new Test(); obj.x; // 3
- 作為構造函數調用,
- 通過
改變call/apply
指向,将類數組對象轉換為數組,this
function exam(a, b, c, d, e) { // 先看看函數的自帶屬性 arguments 什麼是樣子的 console.log(arguments); // 使用call/apply将arguments轉換為數組, 傳回結果為數組,arguments自身不會改變 var arg = [].slice.call(arguments); console.log(arg); } exam(2, 8, 9, 10, 3); // { '0': 2, '1': 8, '2': 9, '3': 10, '4': 3 } // [ 2, 8, 9, 10, 3 ] // 也常常使用該方法将DOM中的nodelist轉換為數組 // [].slice.call( document.getElementsByTagName('li') );
- 根據自己的需要靈活修改
指向this
var foo = { name: 'joker', showName: function() { console.log(this.name); } } var bar = { name: 'rose' } foo.showName.call(bar);
總結
我們可以将平時通過括号、通過
.
、通過
new
去使用函數的方式,看做是
call/apply
的文法糖,是簡寫版,想要深入了解函數的調用,就要學好
call
。
關于
this
的部分已經總結完了,希望這篇文章有助于你準确的了解
this
關鍵字,能夠真正學到東西。
參考
this 的值到底是什麼?一次說清楚
你怎麼還沒搞懂 this?
JS 的 new 到底是幹什麼的?
Javascript 的 this 用法
全方位解讀this
====================================================================================================
作者:星木
歡迎任何形式的轉載,但請務必注明出處。
限于本人水準,如果有不當之處,還請不吝賜教。