Javascript 如何绑定';这';prototype.object上的上下文是否正确?

Javascript 如何绑定';这';prototype.object上的上下文是否正确?,javascript,scope,Javascript,Scope,代码示例: function Test() { this.name = 'test' } Test.prototype.normal = function() { console.log('normal', this.name); }; Test.prototype.special = { name: 'special', start: function () { console.log("special", this.name); }

代码示例:

function Test() {
    this.name = 'test'
}

Test.prototype.normal = function() {
    console.log('normal', this.name);
};

Test.prototype.special = {
    name: 'special',
    start: function () {
        console.log("special", this.name);
    }
}

test = new Test;

test.normal(); // Response 'normal, test'

test.special.start(); // Response 'special, special'
我想要
special.start
函数记录“special,test”


我怎样才能做到这一点?我使用的是coffeescript,所以一个咖啡示例会很受欢迎,但是一个javascript示例也可以!提前谢谢

我想你的问题是关于函数中的这个参数。尝试使用apply或call方法

test=function(){this.name='test';}
test.prototype.special={name:'special',start:function(){alert(this.name)}
var t=新测试();
t、 特殊启动呼叫(t);

t、 特殊的。开始()我想你的问题是关于函数中的这个参数。尝试使用apply或call方法

test=function(){this.name='test';}
test.prototype.special={name:'special',start:function(){alert(this.name)}
var t=新测试();
t、 特殊启动呼叫(t);
t、 特殊的。开始()
  • 的值在调用时由函数的调用方式决定
  • 您希望绑定到
    test
    (实例),而不是
    test
    (构造函数)
  • 如果您不想进行特定的调用时间调整,而是将函数预绑定到
    test
    实例,那么在您拥有一个实例之前,这显然是不可能发生的,并且必须针对每个实例单独进行。因此,唯一的解决办法是:

    function Test() {
        this.special = {
            start: (function () { ... }).bind(this)
        };
    }
    
    也许您希望在原型上定义函数而不是内联函数;但是您仍然需要在构造函数中绑定它:

    function Test() {
        this.special = {
            start: this._start.bind(this)
        };
    }
    
    Test.prototype._start = function () { ... };
    
  • 的值在调用时由函数的调用方式决定
  • 您希望绑定到
    test
    (实例),而不是
    test
    (构造函数)
  • 如果您不想进行特定的调用时间调整,而是将函数预绑定到
    test
    实例,那么在您拥有一个实例之前,这显然是不可能发生的,并且必须针对每个实例单独进行。因此,唯一的解决办法是:

    function Test() {
        this.special = {
            start: (function () { ... }).bind(this)
        };
    }
    
    也许您希望在原型上定义函数而不是内联函数;但是您仍然需要在构造函数中绑定它:

    function Test() {
        this.special = {
            start: this._start.bind(this)
        };
    }
    
    Test.prototype._start = function () { ... };
    

    根据对Kira答案的评论,补充已经给出的答案,您似乎对范围界定的工作方式有一个根本性的误解。Javascript有词法范围,意思是范围由源代码的结构定义,只有一个例外:
    this
    是动态作用域,这意味着作用域由调用方定义。代码:

    bar = 3
    test = (foo) ->
      foo + bar # bar can be seen, because its in an outer scope test can see
    
    到目前为止还不错。现在让我们定义一个类:

    class Test
      constructor: (@foo) ->
      getFoo: -> @foo
    
    getFoo
    部分相当于
    Test.prototype.getFoo=function…
    this
    (@)的范围是
    getFoo
    getFoo
    的调用程序确定
    this

    obj1 = new Test 2
    obj1.getFoo() # 2
    
    fn = Test.prototype.getFoo;
    fn()
    
    fn
    现在是一个独立的函数,而不是
    obj1
    的方法。当我们调用
    fn
    时,会发生以下两种情况之一。如果我们处于严格模式,它将抛出一个错误。因为我们在全局上下文中调用
    ,所以
    getFoo
    中的
    是未定义的。在非严格模式下,它将是全局
    窗口
    ,它将查找可能不存在的foo属性

    我们可以通过
    绑定
    调用
    、或
    应用
    强制

    obj2 =
      foo: 3
    
    Test.prototype.getFoo.call(obj) # 3
    
    这里我们使用它来“借用”测试类的方法。那么bind从何而来?假设我们的类有一个我们知道将在不同上下文中使用的方法,如事件处理程序:

    class Test
      constructor: (@foo) ->
        @clickHandler = Test.prototype.clickHandler.bind this
    
      clickHandler: (e) ->
        console.log @foo
    

    因为我们将把方法传递给
    .addEventListener
    这个
    上下文将消失,这意味着我们需要将它绑定到每个实例,这是我们在构造函数中所做的。

    要根据对Kira答案的评论添加到已经存在的答案中,您似乎对范围界定的工作方式有一个根本性的误解。Javascript有词法范围,意思是范围由源代码的结构定义,只有一个例外:
    this
    是动态作用域,这意味着作用域由调用方定义。代码:

    bar = 3
    test = (foo) ->
      foo + bar # bar can be seen, because its in an outer scope test can see
    
    到目前为止还不错。现在让我们定义一个类:

    class Test
      constructor: (@foo) ->
      getFoo: -> @foo
    
    getFoo
    部分相当于
    Test.prototype.getFoo=function…
    this
    (@)的范围是
    getFoo
    getFoo
    的调用程序确定
    this

    obj1 = new Test 2
    obj1.getFoo() # 2
    
    fn = Test.prototype.getFoo;
    fn()
    
    fn
    现在是一个独立的函数,而不是
    obj1
    的方法。当我们调用
    fn
    时,会发生以下两种情况之一。如果我们处于严格模式,它将抛出一个错误。因为我们在全局上下文中调用
    ,所以
    getFoo
    中的
    是未定义的。在非严格模式下,它将是全局
    窗口
    ,它将查找可能不存在的foo属性

    我们可以通过
    绑定
    调用
    、或
    应用
    强制

    obj2 =
      foo: 3
    
    Test.prototype.getFoo.call(obj) # 3
    
    这里我们使用它来“借用”测试类的方法。那么bind从何而来?假设我们的类有一个我们知道将在不同上下文中使用的方法,如事件处理程序:

    class Test
      constructor: (@foo) ->
        @clickHandler = Test.prototype.clickHandler.bind this
    
      clickHandler: (e) ->
        console.log @foo
    

    因为我们将把这个方法传递给
    .addEventListener
    这个
    上下文将消失,这意味着我们需要将它绑定到每个实例,就像我们在构造函数中做的那样。

    Thx Kira!但是现在我需要经常使用call或apply。我不能预绑定吗?
    prototype
    中的@Dex变量由所有实例共享。如果将函数绑定到一个实例,则会破坏任何其他实例的
    绑定。也许你不应该使用
    prototype
    @ZombieChowder,最好尽可能在链接上有属性。这里有Function.bind方法,而不是调用test.special.start(),你可以像test.start()@Kira一样调用
    bind
    方法就是我说的,它会破坏所有其他函数