module1.init($div) // 語法糖
module1.init.call(module1,$div) // 等價
詳解
this 永遠在函數調用時確定,只是由于語法糖的存在,我們在實際使用時會受到使用場景(瀏覽器/庫)內部this指向的不同的影響。
- 由于語法糖的存在,我們在平常調用函數時很少使用.call(this,argument)的形式
- 所以如果你自己指定this,就call
例子
let module1 = {
elment:null,
init: ($div)=>{
this.element = $div
this.bindEvents()
},
bindEvents:function(){
let $div = this.element
$div.on('click', fucntion(e){
console.log('div is clicked')
})
$div.on('click', 'button', this.onClickButton)
// 瀏覽器
// when user click button
// fn.call('button', {target:'button',currentTarget:'button'})
// 所以這里只跟調用時有關
$div.on('change', 'input', function(e){
console.log(xxx)
})
},
}
總結
一般情況下,
- 當函數作為對象方法調用時,this指向調用該方法最靠近的對象成員,因此:
- 當函數被賦予另一個變量時,函數內部的this的指向會改變,其原因是調用他的對象有變更
- 可以理解為對象即執行該函數的環境,在頂級作用域下執行函數,this指向全局變量(瀏覽器中為window)
var a = {
b: {
m: function() {
console.log(this.p);
},
p: 'Hello'
}
};
var hello = a.b.m;
hello() // undefined
var hello = a.b
hello() // Hello
- 構造函數中的this默認綁定為被創建的新對象
原理:
- 創建一個空對象,作為將要返回的對象實例
- 將這個空對象的原型指向prototype屬性
- 將這個空對象的值賦給函數內部的this關鍵字
- 開始執行構造函數內部代碼
參考前面的方法,總結為
var a = function(){
this.balaba = 123;
}
var b
b = {}
Object.setPrototypeOf(b, a)
a.call(b)
當函數被當做事件處理函數時,this指向觸發事件的函數
內聯事件處理函數的this指向監聽器所在的DOM元素
當函數作為嵌套函數調用時, this指向全局對象(非嚴格模式下)或者undefined(嚴格模式)而不是其外包函數的上下文
var o = {
f1: function () {
console.log(this);
var f2 = function () {
console.log(this);
}();
}
}
o.f1()
// Object
// Window
// 上面等價于下面
var temp = function () {
console.log(this);
};
var o = {
f1: function () {
console.log(this);
var f2 = temp();
}
}
// 解決辦法
var o = {
f1: function() {
console.log(this);
var that = this;
var f2 = function() {
console.log(that);
}();
}
}
o.f1()
// Object
// Object
怎么看this
- console.log()
- 看瀏覽器/jQuery/DOM 源代碼
- 看API 文檔
bind()
bind()
會返回一個新的函數,該函數有指定的this,且不被call()
/ apply()
bind的使用例子
根據前面總結的第3條和第5,如果需要在一個函數中的事件監聽設置this指向外包函數的this,可以用bind綁定this的指向,否則,監聽事件觸發時this會指向觸發事件的元素。
var box = document.getElementById('box');
box.x = 'box'
function outFunc() {
this.x = 'outFunc';//給全局對象window.x賦值(相當于賦值全局變量)
box.addEventListener('click', func.bind(this), false); // bind(this) 的this 指向outFunc() 中的this,又等于指向window
}
function func() {
console.log(this.x); //輸出outFunc 使用bind設置this的值
}
參考:
JS中的this簡單描述
addEventListener中事件函數的this指向
MDN - JavaScript - this