THIS知识点
- 函数的执行主体,和执行上下文不是一个概念
- this是谁和函数在哪执行,以及在哪定义没有必然的联系
按照以下规律来确定执行主体是谁:
- 给当前元素的某个事件行为绑定方法,事件触发,执行对应的方法,方法中的this是当前元素本身(排除:IE6~8基于attachEvent实现的DOM2事件绑定,绑定方法中的this不是操作的元素,二是window)
document.body.onclick = function() {
// this : body
}
- 函数执行,首先看函数名之前是否有“点”,有“点”,“点”前面是谁this就是谁,没有“点”this就是window(在JS的严格模式下,没有“点”,方法中的this是undefined)
"use strict" //全局上下文开启严格模式
(function() {
"use strict" // 当前上下文开启严格模式
)()
2.1 自执行函数中的this一般都是window/undefined<br>
2.2 回调函数中的this一般也是window/undefined<br>
3. 构造函数中的this是当前类的实例
-
箭头函数没有自己的this,用到的this都是上下文中的this
-
基于call/apply/bind可以强制改变this的指向
练习题
var num = 10
var obj = {
num: 20
}
obj.fn = (function(num) {
this.num = num * 3
num++
return function(n) {
this.num += n
num++
console.log(num)
}
})(obj.num)
var fn = obj.fn
fn(5)
obj.fn(10)
console.log(num, obj.num)
let obj = {
fn: (function() {
return function() {
console.log(this)
}
})()
}
obj.fn()
let fn = obj.fn
fn()
/**
* obj.fn = 自执行函数的返回结果
* fn = 0x000000 (作用域:EC(G),代码字符串“console.log(this)”)
*/
let obj = {
fn: (function() {
return function() {
console.log(this)
}
})()
}
obj.fn() // obj.fn() => obj.0x000000() => 输出this:obj
let fn = obj.fn // fn = 0x00000
fn() // 输出this:windown
var fullName = 'language'
var obj = {
fullName: 'javascript',
prop: {
getFullName: function() {
return this.fullName
}
}
}
console.log(obj.prop.getFullName())
var test = obj.prop.getFullName
console.log(test())
var fullName = 'language' // 也会给window一份,window.fullName = 'language'
var obj = {
fullName: 'javascript',
prop: {
getFullName: function() {
return this.fullName
}
}
} // 堆内存0x000000
console.log(obj.prop.getFullName()) //undefined
// this => obj.prop
// this.fullName = obj.prop.fullName => undefined
var test = obj.prop.getFullName
console.log(test()) // 'language'
// this => window
// window.fullName = 'language'
var name = 'window'
var Tom = {
name: 'Tom',
show: function() {
console.log(this.name)
},
wait: function() {
var fun = this.show
fun()
}
}
Tom.wait()
var name = 'window'
var Tom = {
name: 'Tom',
show: function() {
console.log(this.name) // fun执行,this => window window.name = 'window'
},
wait: function() {
var fun = this.show // this => Tom fun = Tom.show
fun()
}
}
Tom.wait()
window.val = 1
var json = {
val: 10,
dbl: function() {
this.val *= 2
}
}
json.dbl()
var dbl = json.dbl
dbl()
json.dbl.call(window)
alert(window.val + json.val)
window.val = 1 // 第二次执行后变成2
var json = {
val: 10, // 20
dbl: function() {
/**
* 第一次执行:this => json
* json.val *= 2 => 20
* 第二次执行: this => window
* window.val *= 2 => 2
* 第三次执行:通过call rangthis指向 window
* window.val *= 2 => 4
*/
this.val *= 2
}
}
json.dbl()
var dbl = json.dbl
dbl() //
json.dbl.call(window)
alert(window.val + json.val) // 4+20 => 24 alert弹出的都是字符串,缩影应该是'24'
(function () {
var val = 1;
var json = {
val: 10,
dbl: function () {
val *= 2;
}
};
json.dbl();
alert(json.val + val);
})();
(function () {
var val = 1; // 第一次执行后 val = 2
var json = {
val: 10,
dbl: function () {
// dbl 作用域:EC(G)
// val不是私有的,作用域链想上找 是自执行函数执行创建出来的上下文中的变量
val *= 2; // 全局val = 2
}
};
json.dbl();
alert(json.val + val); // 10 + 2 = 12 => '12'
})();