对于初学 JS 的同学来说,可能存在完全搞不懂 this 到底指向哪里,指东指西,指向意料之外的对象。
—— what's fuckkkk... 你是否也有这种感觉呢?
好了,我们就不要逼叨叨了, 进入主题一起来看看 this 到底指向哪里吧:
this:被谁调用,就指向谁。
如何理解这句话呢?我们稍稍放慢脚步,结合案例一点点进行分析:
- 案例一:
var a = 1;
console.log(a)
console.log(this.a); // 1
console.log(window.a) // 1
console.log(this == window) //true
案例一分析:
1:全局执行 var a = 1, 相当于给 wiondow 对象添加了 a 属性,并赋值为 1
2:在全局下执行 console.log(...),此时的 this 就是指向 window 且是同一个对象
- 案例二
function test() {
var a = 1;
console.log(a) // 1
console.log(this); //window
console.log(this.a); // undefined
}
test();
console.log(this.a); // undefined
案例二分析:
结合预编译来分析
GO:{
test: function(){}
}
AO: {
a: undefined --> 1
}
在哪里调用,就指向哪里
1:全局调用 test 函数,相当于执行了:window.test()
2:此时 test 函数中的 this 指向 window (在哪里调用,就指向哪里)
3:预编译的信息可以看出,GO 中没有 a 变量 ---> undefined
- 案例三:
function test() {
var a = 1;
console.log(a) // 1
console.log(this); //window
console.log(this.a); // undefined
function inner() {
console.log(this.a); // undefined
console.log(this); // window
}
inner();
}
test();
案例三分析:
结合预编译来分析
GO:{
test: function(){}
}
AO: {
a: undefined --> 1
inner: function() {}
}
在哪里调用,就指向哪里
1:全局调用 test 函数,相当于执行了:window.test()
2:此时 test 函数中的 this 指向 window
3:预编译的信息可以看出,GO 中没有 a 变量 ---> undefined
4:虽然在 test() 中执行 inner(), 但不要忘记了是 test() 是在全局下被调用的,因此 inner() this 指向 wiondow
- 案例四:
var obj = {
names: '人间富贵花',
fn: function() {
console.log(this.names) // 人间富贵花
console.log(this) // {name: '人间富贵花, fn: function(){}}
}
}
obj.fn()
案例四分析:
结合预编译来分析
GO:{
obj: undefined ---被赋值为一个对象--> {}
}
1:被谁调用就指向谁
2: obj对象有上挂载了a 、 fn 两个属性
3:obj.fn()执行,fn 函数中的 this 指向 obj
- 案例五:(注意)
var obj = {
names: '人间富贵花',
fn: function() {
console.log(this.names) // 人间富贵花
console.log(this) // {name: '人间富贵花, fn: function(){}}
}
}
window.obj.fn()
很多同学看到这里就会认为:函数是在 windon 下调用的, this 为什么不指向 window 呢?
说明: 如果一个函数中有 this , 但是他没有被上一级对象调用,那么 this 指向 window;如果被上一级对象调用,则指向上一级对象。
案例五分析:
1: 案例五和案例四,其实是没有任何区别的,都是在 window 下执行的
2:为什么 window.obj.fn() 中的 this 没有指向 window 呢?
3:函数中有 this ,但是 fn() 被上一级 obj 调用, 那么 this 指向 obj,而不会指向 window。
结合案例五的分析我们可以看看以下的特殊情况了
- 案例六:
var obj = {
names: "人间富贵花",
info: {
skill: "JavaScript",
fn: function () {
console.log(this); // fn 函数的上一级 info 对象 {skill: '...', fn:function(){}}
console.log(this.names); // undefined
console.log(this.skill); // JavaScript
}
}
};
obj.info.fn();
案例六分析:
1:obj.info.fn() 等同于 window.obj.info.fn()
2: 被谁调用,层级比较多的情况,存在被上一级对象调用,this 指向上一级对象
- 案例七:
var obj = {
names: "人间富贵花",
info: {
skill: "JavaScript",
fn: function () {
console.log(this); //window
console.log(this.names); // undefined
console.log(this.skill);// undefined
}
}
};
var test = obj.info.fn;
test();
哈哈 是不是又懵逼了,为什么:this.names 、this.skill 为 undefined
案例七分析:
1:被谁调用 this 指向谁
2: window 下执行 test() 此时函数中的 this 指向 window
3:window 下是没有names、skill 属性
- 案例八:构造函数
function Person() {
this.name = "人间富贵花";
this.skill = "JavaScript";
console.log(this); // Person{name: '...',skill: '...'}
}
var p = new Person();
console.log(p); // Person{name: '...',skill: '...'}
案例八分析:
1:构造函数 this 指向 我们需要跳出:哪里调用指向哪里的思想
2:通过 new 关键字改变了 this 的指向,将这个 this 指向了实例化后的对象 p
- 案例九: call、apply
var obj = {
names: '人间富贵花',
fn: function(val1, val2) {
console.log(this.names)
console.log(val1 + val2)
}
}
var info = obj.fn
info.call(obj, 1, 2) // '人间富贵花' 3
var test = {
names: 'RJFGH'
}
info.apply(test, [2, 2]) // 'RJFGH' 4
案例九分析:
1:info: function() {}
2:object.call(target, val1, val2...) object.apply(target, [val1, val2...])
3:call 方法改变 this 的指向,指向 obj (target),
4:obj.names: '人间富贵花'
5:info.call(obj, 1, 2) ---> '人间富贵花' 3
6:info.apply(test,[2, 2]) ---> 'RJFGH' 4
补充说明:构造函数 return 的问题
function Person1() {
this.name = '人间富贵花'
console.log(this) // Person1:{...}
return ''
}
var p1 = new Person1()
console.log(p1.name) // 人间富贵花
// -----------------------------------------------------------------------------
function Person2() {
this.name = '人间富贵花'
console.log(this) // Person2:{...}
return 1
}
var p2 = new Person2()
console.log(p2.name) // 人间富贵花
// -----------------------------------------------------------------------------
function Person3() {
this.name = '人间富贵花'
console.log(this) // Person3:{...}
return null
}
var p3 = new Person3()
console.log(p3.name) //人间富贵花
// -----------------------------------------------------------------------------
function Person4() {
this.name = '人间富贵花'
console.log(this) // Person4:{...}
return []
}
var p4 = new Person4()
console.log(p4.name) // undefined
// -----------------------------------------------------------------------------
function Person5() {
this.name = '人间富贵花'
console.log(this) // Person5:{...}
return function(){}
}
var p5 = new Person5()
console.log(p4.name) // undefined
// -----------------------------------------------------------------------------
function Person6() {
this.name = '人间富贵花'
console.log(this) // Person6:{...}
return {}
}
var p6 = new Person6()
console.log(p6.name) // undefined
从 Person1、Person2、Person3、Person4、Person5、Person6 例子可以看出:
如果返回值 是一个对象,this 指向被改变且指向返回的这个对象
如果返回值不是一个对象,this 指向不变还是指向构造函数的实例
总结:
- 谁调用指向谁
- 存在对象层级调用的,被上一级调用,this 就指向上一级,否则指向 window
- 构造函数,指向实例化的对象
- call、apply,this 指向 target
- 构造函数 return 的结果如果是一个对象,则会改变 this 的指向,否则不会改变指向,依旧指向实例化的对象
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!