javascript - 关于this的一个小问题?
巴扎黑
巴扎黑 2017-04-10 17:45:50
[JavaScript讨论组]

代码如下:

function foo() {
    console.log(this.a);
}
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo(); // 3

// 如果
(p.foo = o.foo)(); // 2

// 如果
p.foo = o.foo;
p.foo(); // 4

(p.foo = o.foo)(); 和 p.foo = o.foo; p.foo();这两个foo,执行结果为什么会不同,这两种写法有不一样吗?

巴扎黑
巴扎黑

全部回复(7)
怪我咯

建议楼主点击F12,直接console.dir()这两种情况的foo,在里面会找到一个叫constructor的东西。
这个constructor,实际上就是this的指向。

  • 对于第一个:

o.foo();

他的constructor指向o这个对象,因此this指向的是o,打印2;

  • 第二个:

(p.foo = o.foo)();
//相当于
function f() {
    p.foo = o.foo;
}

f();

此时的constructor指向的其实是window,为什么呢?
因为constructor的初始化需要的是创建对象,因此o本身就是申明的对象,那么他的constructor就指向自己。
而调用f,这个f是在window下创建的(浏览器中所谓的全局环境其实就是window对象,你懂的),因此相当于调用了window.f(),那constructor自然指向window,而window中声明了a=2,那么用括号封闭立即执行的方法,都是通过window对象执行的(除非这整段函数封闭在另一个作用域中执行),自然this就指向window,从而this.a指向值为2的这个a。

  • 第三个:

p.foo();//

函数由p执行,那么construtor指向的就是对象p,this也就指向p,因此this.a === p.a;//true

PS:constructor是可写的,可以手动改变。

通过new操作符可以初始化一个constructor的指向,new的作用就是创建一个对象的实例,constructor也就指向了一个新的执行环境“在这个对象中”(百度“JS函数对象”)。
伊谢尔伦

前面一种赋值语句会返回foo函数,后面跟括号就是直接调用,并没有作为对象的方法调用。

PHPz

其实仔细捋一下还是可以理解的
1、(p.foo = o.foo)();这句代码分为两部分理解,前一个括号内将o.foo赋值给p.foo,括号最终的运算结果是(foo),后一个括号再执行时,this是指向window的,所以输出的a为2就不难理解了。注意:这里执行的函数是前一个括号里的返回的那个函数,而不是p.foo
2、p.foo = o.foo;先给p.foo赋值,然后执行p.foo(); 这时this肯定是指向p的,输出为4

黄舟

http://www.cnblogs.com/aaronj...、
请看题目5对于这类问题的详细解答

巴扎黑

https://github.com/leadzen/bl...

巴扎黑

(p.foo = o.foo)(); 和 p.foo = o.foo; p.foo();

(p.foo = o.foo)()的返回值是一个function,就是(function foo(){})(),调用的时候window是this。

p.foo = o.foo; p.foo();。是吧p.foo = function(){}。你调用p.foo()时候,p是this

ringa_lee

理论的感觉太难讲。。。就随便说一个简简单单的规律吧。。。
首先,请观察下this是指向本身对象的几种情况:

o.foo();//3
p.foo();//4

然后,再观察下this指到不知道哪里去的情况:

(p.foo=o.foo)();

看出来了吗?
其实看this指向谁,就是看上下文执行环境嘛。一个函数要执行,肯定要带()这个符号吧,然后,你就顺着这个()往前看,当看到诸如a();b();c()这类的,不用说,里面的this指向肯定是window
当看到诸如a.b();c.e()这类的,里面的this指向肯定是a和c;
然后,回到题目
(p.foo=o.foo)(),第一个括号里面是什么?p.foo?naive
你可以这样理解:
因为套了个括号,js要把括号里面的东西完全处理完,怎么才算是处理完?那就是p.foo=o.foo=function(){console.log},然后处理到最彻底,就是变成了(function(){console.log(this)})(),好了,现在看第二个括号前面的内容有什么什么.吗?没有,没有自然是指向window

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号