分配后,JavaScript函数绑定(此关键字)将丢失

nan*_*din 9 javascript

这是JavaScript中最神秘的功能之一,在将对象方法分配给其他变量后,绑定(此关键字)将丢失

var john = {
  name: 'John',
  greet: function(person) {
    alert("Hi " + person + ", my name is " + this.name);
  }
};

john.greet("Mark"); // Hi Mark, my name is John

var fx = john.greet;  
fx("Mark"); // Hi Mark, my name is 
Run Code Online (Sandbox Code Playgroud)

我的问题是:

1)作业背后发生了什么?var fx = john.greet; 是按价值复制还是按参考复制?fx和john.greet指向两个不同的功能,对吧?

2)因为fx是一个全局方法,所以范围链只包含全局对象.Variable对象中属性的值是多少?

Viv*_*ath 13

john.greet("Mark")实际上调用一个函数.当你这样做时var fx = john.greet;,你得到了对该功能的引用.因此,当你打电话给它时,this并不是必然的john.你实际上做的是window.fx("Mark")thiswindow对象.当你说它处于全球范围内时,你走在了正确的轨道上.在这个特定的实例中,全局对象是window,fx实际上也是如此window.fx.

如果有函数引用,则应使用call或者apply如果要设置值this.试着这样做:

fx.call(john, "Mark");
Run Code Online (Sandbox Code Playgroud)

在第一个参数callapply是用于值this在函数调用的上下文.

编辑

有些人提到这里的真正问题可能是围绕对象文字与对象实例的混淆.您正在创建一个对象文字,其行为也类似于单身.您无法创建该对象的新实例.在这种情况下john是对该文字的引用.在该上下文this中,函数greet指的是对象文字本身.因此,当你打电话时john.greet("Mark"),this必然会john.

当您单独获取引用john.greet并将其分配给全局变量时,您实际上是这样做的:

var fx = function(person) {
   alert("Hi " + person + ", my name is " + this.name);
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,thiswindow,因为fx基本上window.fx(因为这里的全局对象是window.假设这个代码被包装在另一个函数中,那么全局对象将引用该函数.

如果要创建对象的多个实例,可以执行以下操作:

var Person = function(name) {
    var self = this; //maintains a reference to the instance

    this.name = name;
    this.greet = function(name) {
        alert("Hi " + name + ", my name is " + self.name);
    }
}

var john = new Person("John");
john.greet("Mark"); // alerts "Hi Mark, my name is John"

var fx = john.greet;
fx("Mark"); // also alerts "Hi Mark, my name is John"
Run Code Online (Sandbox Code Playgroud)

这里,self变量(函数的本地)维护对实际实例的引用,因为您在this创建对象时将其绑定到它.

在Javascript中有许多与OOP相关的最佳实践.你可以谷歌找出(有很多链接).我建议特别是读道格拉斯克罗克福德的东西.


CMS*_*CMS 6

1)fx并且john.greet指的是相同的函数对象,对象的赋值操作,通过引用工作.

为原始值,比如String,Number,Boolean undefinednull,该值的副本将被制成.

2)该this值指的是全局对象.

this值不是变量对象的属性,它与范围链无关,是一个特殊的保留字,并且在调用函数时隐式确定(您也可以通过call或显式设置它apply).

JavaScript内部处理一个Reference type由两个组件组成的基础对象属性名称,当调用一个函数时,this通过获取基础对象(通过内部GetValue操作)隐式确定该值.

最后,this隐式设置的最后一种情况是当您使用new运算符调用函数时,this关键字将引用新创建的对象.

所以,简单地说,这里是如何this工作的含蓄:

1-当函数作为方法调用时(该函数作为对象的成员调用):

obj.method(); // 'this' inside method will refer to obj
Run Code Online (Sandbox Code Playgroud)

2- 正常函数调用:

myFunction(); // 'this' inside the function will refer to the Global object
// or 
(function () {})();
Run Code Online (Sandbox Code Playgroud)

3-使用new操作员时:

var obj = new MyObj(); // 'this' will refer to a newly created object.
Run Code Online (Sandbox Code Playgroud)