3

我相当肯定这是不可能的,但想看看是否有人对如何使其成为可能有一些巧妙的想法。

我希望以下代码工作:

var x = new foo();
x.a.getThis() === x; // true

换句话说,我想x.a.getThis参考thisx这种情况下。说得通?

为了让它深入一层很简单:

function foo(){}
foo.prototype.getThis = function(){ return this; }
var x = new foo();
x.getThis() === x; // true

有一件事,我希望它可以作为原型工作,而不是通过手动绑定来“作弊” this

function foo(){
    this.a = {
        getThis : (function(){ return this; }).bind(this)
    };
}

尽管上面是我想要实现的完美功能示例,但我只是不希望每个实例都有所有额外的功能:)

仅供参考,这里的实际用例是我正在创建类来表示节点中的 Cassandra 对象,并且我希望能够通过引用超级列 --> 列族 --> 列foo.a.bfoo在深层功能。

4

3 回答 3

3

如果没有某种强制绑定,您将无法做到这一点。你说你不想“作弊”,但这违反了关于什么this是标准的规则,所以你必须作弊。但是JS让你作弊,所以这一切都很好。

顺便说一句,咖啡脚本的价值使这变得如此微不足道。

foo = ->
  @a = getThis: => this

粗箭头=>从它被调用的范围中保留了 this for 的上下文。这使您可以轻松地将上下文转发到另一个级别。

该代码被编译成这个 JS:

var foo;
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
foo = function() {
  return this.a = {
    getThis: __bind(function() {
      return this;
    }, this)
  };
};

这基本上只是做你说你不想做的事情。


或者,如果值不必this特别指定,您可以在子对象中设置“所有者”。

var A = function(owner) {
  this.owner = owner;
};
A.prototype.getThis = function() {
  return this.owner;
};
var Foo = function() {
  this.a = new A(this);
};

var foo = new Foo();

if (foo.a.getThis() === foo) {
    alert('Happy dance');
} else {
    window.location = 'https://commons.lbl.gov/download/attachments/73468687/sadpanda.png';
}

http://jsfiddle.net/4GQPa/

还有咖啡脚本版本,因为我是一个充满激情和不合理的狂热者:

class A
  constructor: (@owner) ->
  getThis: -> @owner

class Foo
  constructor: -> @a = new A(this)

foo = new Foo()
if foo.a.getThis() is foo
  alert 'Happy Dance'
else
  window.location = 'https://commons.lbl.gov/download/attachments/73468687/sadpanda.png'
于 2011-05-27T06:31:58.473 回答
0

由于函数的this的值是由调用设置的,因此如果不在开始时绑定值就不可能可靠地执行。您无法事先知道它将如何被调用,或者哪些函数需要特殊或受限调用来“保留” this -> this关系。

函数或调用者的this可能是任何对象,可能根本没有this -> this。考虑:

var x = {
  a : {
    b: function() {return this;}
  }
}

当你调用 时x.a.b(),bthis是 a。但如果你这样做:

var c = x.a.b;
c(); // *this* is the global object

或者

x.a.b.call(someOtherObject);

在这些情况下, this -> this的价值是什么?

于 2011-05-27T06:48:59.613 回答
0

回答我自己的问题,因为其他人可能会觉得它有用。不确定我最终是否会选择这个或 Squeegy 的解决方案。这些函数只定义一次,然后包含对象被克隆并parent = this注入其中:

function foo(){
    var self = this, nest = this.__nestedObjects__ || [];

    nest.forEach(function(prop){
        self[prop] = extend({ parent : self }, self[prop]);
    });
}

// bound like this so that they're immutable
Object.defineProperties(foo.prototype, {
    bar : {
        enumerable : true,
        value : {
            foobar : function(){
                return this.parent;
            },
            foo : function(){},
            bar : function(){}
        }
    },
    __nestedObjects__ : { value : ['bar'] }
});

var fooInst = new foo();
console.log(fooInst.bar.foobar() == fooInst);

或基于 Squeegy 的解决方案:

function foo(){
    for(var cls in this.__inherit__){
        if(!this.__inherit__.hasOwnProperty(cls)){ continue; }

        this[cls] = new (this.__inherit__[cls])(this);
    }
}

var clsA;
// bound like this so that they're immutable
Object.defineProperties(foo.prototype, {
    __inherit__ : { value : {
        bar : clsA = function(parent){
                Object.defineProperty(this, '__parent__', { value : parent });
            }
        }
    }
});

clsA.prototype = {
    foobar : function(){
        return this.__parent__;
    }
};

var fooInst = new foo();
console.log(fooInst.bar.foobar() == fooInst);
于 2011-05-27T06:50:09.560 回答