Javascript绑定到对象

Lah*_*nna 3 javascript

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

我尝试这个例子时,我得到以下消息,undefined rocks! 而不是Ruby rocks!.你能解释一下为什么会这样吗?

Gab*_*iel 7

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

JavaScript 函数在调用时具有执行上下文,使得this关键字绑定到从中调用它们的对象.如果调用john.says()函数的执行上下文,则会有一个this指向的关键字john.如果您将全局变量分配给在对象上找到func的方法says,john则将执行上下文更改为全局对象.当您调用该func函数时,this取消引用window(或undefined*)和since window.skill是未定义的,says将该值强制转换为字符串以将其与字符串'rocks!'连接.

如何使用bind保证执行上下文

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

var func = john.says.bind(john);
Run Code Online (Sandbox Code Playgroud)

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

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

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;
}
Run Code Online (Sandbox Code Playgroud)

如何使用闭包保证值

您可以skill直接从方法引用该值,因此根本不需要上下文:

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!');
  }
}
Run Code Online (Sandbox Code Playgroud)

如何使用call和apply在调用时保证执行上下文

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

func.call(john /*, optional arguments... */);
func.apply(john /*, optional arguments as an array */);
Run Code Online (Sandbox Code Playgroud)

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

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

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!")
Run Code Online (Sandbox Code Playgroud)

更多阅读:

*"use strict"激活表示JavaScript未来的特殊严格模式.当尚未设置上下文时,此特殊严格执行环境将不会解析为全局对象,而是将其解析为适当的作用域值undefined.