javascript - 闭包中的this
伊谢尔伦
伊谢尔伦 2017-04-10 15:44:13
[JavaScript讨论组]
var name = "the window";

var object = {
    name:"my object";
    getName:function(){
        return this.name;
    }
};

object.getName();    //"my object"
(object.getName)();    //"my object"
(object.getName=object.getName)();    //"the window"

第二和第三个输出为什么不一样,尤其是第三个,怎么理解?

伊谢尔伦
伊谢尔伦

小伙看你根骨奇佳,潜力无限,来学PHP伐。

全部回复(5)
PHP中文网

函数里的 this 取决于你调用它时的上下文。

  1. 当函数作为对象的方法调用时,this 指向这个对象。

  2. 当你直接执行它时,this 指向 window。

  3. 你还可以用call, applay, bind方法来指定this

下面有一段示例帮助你理解:

var say = function () {
  console.log('My name is', this.name);
};

var jack = {
  name: 'Jack',
  say: say
};

var rose = {
  name: 'Rose',
  say: say
};

jack.say(); // My name is Jack
rose.say(); // My name is Rose

window.name = '世界之窗';
say(); // My name is 世界之窗

题目里的(object.getName=object.getName)();这种写法有意思的地方在于,object.getName=object.getName这个赋值操作的返回结果是下面这个函数体,

function(){
    return this.name;
}

所以整个这一句的执行结果等同于

(function(){
    return this.name;
})();

结合此答案最前面提到的第 2 点,可知这里的this就指向window

其实这个问题跟闭包无关,跟上下文(context)有关。闭包影响作用域,上下文影响this

迷茫

这个是 Javascript 高级程序设计(version3, p183)中的例子吧,其实书上已经解释很清楚了:

  1. (object.getName)()object.getName() 是等价的,因为 xxx.xxx(成员访问) 的优先级高于 xxx(xxx)(函数调用),所以加不加圆括号不影响结果(关于运算符优先级可参考 运算符优先级);

  2. (object.getName=object.getName) 是一个赋值表达式,赋值表达式求值结果是右值,所以该表达式的值是 getName函数。你可以这么理解:(object.getName=object.getName)() 等价于 var b; (b=object.getName)() 等价于 var b; b=object.getName; b()

  3. 严格模式下,(object.getName=object.getName)() 会报错,因为严格模式下,禁止 this 关键字指向全局对象。

伊谢尔伦

object.getName=object.getName 返回的是一个单独的function
等同于

(function(){return this.name;})();
迷茫

一和二应该是一样的, . 和 ()优先级相同,所以不影响的

至于三,相当于 (c=object.getName)(),也就是相当于c(),而c直接呗调用,其this也就指向window咯

PHP中文网
var name = "the window";
var object = {
    name:"my object";
    getName:function(){
        return this.name;
    }
};

object.getName(); //"my object"
(object.getName)(); //"my object"
(object.getName=object.getName)(); //"the window"

第1个方法好理解,就是普通对象的方法调用,this绑定到 object

第2个方法(object.getName)();乍一看,(object.getName)不是执行了运算嘛,返回的结果应该一个函数对象,结果应该和方法3相同啊,其实不然;
()为一个分组操作符,对分组操作符运算规则的定义是:计算分组操作符中的表达式,如果计算结果是一个应用,那么不会计算这个引用所指向的实际值返回(这个计算结果就是getName函数对象),这样的话(object.getName)的计算结果和object.getName的计算结果相同。故其行为就是一个对象的方法调用

第3个方法的执行步骤
1) object.getName=object.getName,
右边的object.getName计算后,因为其左边是一个=赋值操作符号,所以其要获取object.getName对应的实际函数对象,并把这个函数对象赋予右边的object.getName属性
同时整个赋值操作将返回左边object.getName对应的实际函数对象
2)执行对1返回的结果执行调用,此时只是一个简单的函数调用,和object对象无关,this 绑定到 windows 全局对象

不足之处多多指正

具体可参考 ECMAScript语言规范中的描述
ECMAScript Language Specification
http://bclary.com/2004/11/07/#a-11.1.6

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

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