Javascript绑定到对象

时间:2014-04-08 05:16:20

标签: javascript

function Developer(skill) {
    this.skill = skill;
    this.says = function() {
        alert(this.skill + ' rocks!');
    }
}
var john = new Developer('Ruby');
var func = john.says;
func();

我尝试此示例时,我收到以下消息undefined rocks!而不是Ruby rocks!。  你能解释一下为什么会这样吗。

6 个答案:

答案 0 :(得分:7)

功能执行上下文和this关键字

JavaScript 函数在调用时具有执行上下文,以便this关键字绑定到从中调用它们的对象。如果您致电john.says(),该函数的执行上下文将包含指向this的{​​{1}}关键字。如果您将全局变量john分配给在对象func上找到的方法says,则已将执行上下文更改为全局对象。当您调用john函数时,func取消引用this(或window *)并且由于undefined未定义,window.skill将强制执行将值转换为字符串以将其与字符串'连接起来。岩石'!

如何使用bind

保证执行上下文

您可以将函数的副本绑定到对象(有效地锁定它的上下文引用):

says

如何使用闭包保证执行上下文

或者,您可以通过在构造函数中使用闭包来关闭相关位:

var func = john.says.bind(john);

如何使用闭包来保证值

您可以直接从方法中引用function Developer(skill){ var _this = this; // we keep a reference here this.skill = skill; this.says = function(){ alert(_this.skill + ' rocks!'); // when invoked _this refers to the context at construction } return this; } 值,因此根本不需要上下文:

skill

如何使用call和apply

在调用时保证执行上下文

最后的选项是在调用时使用您想要的上下文调用该方法:

function Developer(skill){
  // because skill is defined in this context, says will refer to this context
  // to get the value of the skill variable.
  this.says = function(){
    alert(skill + ' rocks!');
  }
}

如何使用原型来允许动态执行上下文设置正确

如果我们想在对象实例或类型之间重用一个方法,但在调用时有正确的执行上下文,我们可以使用prototype属性。

func.call(john /*, optional arguments... */);
func.apply(john /*, optional arguments as an array */);

更多阅读:

*"使用严格"激活表示JavaScript未来的特殊严格模式。当尚未设置上下文时,此特殊严格执行环境将无法解析为全局对象,而是将其解析为适当范围的值function Developer(skill){ this.skill = skill; this.says(); } Developer.prototype.says = function(){ alert(this.skill + ' rocks!'); } var john = new Developer("Ruby"); // alert("Ruby rocks!") var tony = new Developer("JavaScript"); // alert("JavaScript rocks!")

答案 1 :(得分:2)

让我们通过实际返回对象来说明发生了什么:

function Developer(skill) {
  this.skill = skill;
  this.says = function() {
    alert(this.skill + ' rocks!');
  }
  return this; //this is basically { skill: skill, says: function() {} }
}

var john = new Developer('Ruby');
var func = john.says; // all it knows is the function() part, has no knowledge of skill
func(); //undefined rocks!

好的,为什么我们会变得不确定?好吧,一旦我们删除了该函数,它就不再具有上下文 - 它不知道this是什么。如果我们这样做:

func.apply(john);

然后我们将John作为this参数传递给我。一种解决方法,它在我们创建它时将值传递给函数:

function Developer(skill) {
  this.skill = skill;
  this.says = function(skill) { //<--calling this function
                return function() { //<--returning this function
                   alert(skill + ' rocks!');
                };
              }(this.skill); //<--passing in the value here
  return this;
}

答案 2 :(得分:1)

因为func()只有该功能,而没有任何其他相关信息。(this.skill)

背景丢失了。调用thisjohn引用says()

但现在,当您致电func() this时,会引用window。因此this.skills将返回undefined,除非您有一个同名的全局变量。

答案 3 :(得分:1)

  1. 调用函数时,this将引用调用该函数的对象。

  2. 当你说

    var func = john.says;
    

    您只是获取功能对象(它不记得定义它的对象)。

  3. 当你调用这个函数时,就像这样

    func();
    

    没有当前对象,在其上调用func。因此,默认情况下,JavaScript将全局对象(浏览器中的window对象)指定为this。由于skill未在全局对象中定义,因此返回undefined

  4. 注意:在严格模式下,如果没有当前对象,this将为undefined

    这就是为什么我们必须将对象显式绑定到函数,就像这个

    func.bind(john)();
    

    Function.prototype.bind将返回一个新函数,该函数绑定到john。因此,当您调用此this时,将引用john

答案 4 :(得分:0)

保持上述模式的最快方法是将this直接绑定到方法this.says = function () { ... }.bind(this);

function Developer(skill) {
    this.skill = skill;
    this.says = function () {
        alert(this.skill + ' rocks!');
    }.bind(this);
}
var john = new Developer('Ruby');
var func = john.says;
func(); // Ruby rocks!

答案 5 :(得分:-1)

试试这个

function Developer(skill) {
    this.skill = skill;
    this.says = function() {
        alert(this.skill + ' rocks!');
    }
}
var john = new Developer('Ruby');
john.says();

工作演示 http://jsfiddle.net/ZENtL/