我相当肯定这是不可能的,但是想知道是否有人对如何使它成为可能有一些巧妙的想法。
我想要以下代码:
var x = new foo();
x.a.getThis() === x; // true
换句话说,在这种情况下,我希望x.a.getThis
引用this
为x
。有意义吗?
为了让这个工作 一个 级别很简单:
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对象,我希望能够引用一个超级列 - > column-family - >通过foo.a.b
列,并在深层函数中保留对foo
的引用。
答案 0 :(得分:3)
如果没有某种强制绑定,你就无法做到这一点。你说你不想“欺骗”,但这违反了this
的标准规则,所以你必须作弊。但JS让你作弊,所以这一切都很好。
foo = ->
@a = getThis: => this
胖箭头=>
从它所调用的范围中保留了它的上下文。这使您可以轻松地将上下文转发到另一个级别。
该代码被编译到这个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';
}
咖啡脚本的版本因为我是一个充满热情和不合理的狂热者:
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'
答案 1 :(得分:0)
由于函数的 this 的值是由调用设置的,因此无法在不启动时绑定值,从而无法可靠地执行。您事先无法知道如何调用它,或者哪些函数需要特殊或限制调用来“保留” this - >这个关系。
函数或调用者的this
可以是任何对象,可能没有 this - >这个。考虑:
var x = {
a : {
b: function() {return this;}
}
}
当你致电x.a.b()
时,b的this
就是了。但如果你这样做:
var c = x.a.b;
c(); // *this* is the global object
或
x.a.b.call(someOtherObject);
的价值是什么 - >这个在这些情况下?
答案 2 :(得分: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);