我有JavaScript组件,具有以下架构:
var MyComponent = function(params)
{
setup(params);
this.doSomething()
{
// doing something
};
function setup(params)
{
// Setup
// Interaction logic
var _this = this; // "this" points to DOMWindow, not to created object
$(".some-element").click(function(){
_this.doSomething(); // it craches here, because of above
});
}
};
Run Code Online (Sandbox Code Playgroud)
当由交互逻辑控制的事情发生时,有时我必须将执行转发到组件的"公共"方法.
在这种情况下,我有"这个"指针的问题.
示例代码演示了它:
var Item = function()
{
this.say = function()
{
alert("hello");
};
this.sayInternal = function()
{
_sayInternal();
};
function _sayInternal()
{
this.say();
};
};
Run Code Online (Sandbox Code Playgroud)
要测试它,
var o = new Item();
o.say(); // alerts "hello"
o.sayInternal();
我收到一个错误:
TypeError:表达式'this.say'[undefined]的结果不是函数.
我认为,这样的行为发生,因为_sayInternal()函数声明(而不是分配给对象,如"this.say =功能()").这样,它在所有创建的对象之间共享,并且像C++中的静态函数一样.
这是真的 ?
不,sayInternal不在创建的对象之间共享。但你是对的,创建的对象无权访问,sayInternal因为它没有分配给它们。该函数仅是构造函数的局部函数。
this总是指调用函数的上下文。如果您像这样调用它func(),那么this指的是全局对象(位于window浏览器中)。如果将函数设置为对象的属性并使用 调用它obj.func(),则将this引用obj。
如果将“绑定”函数分配给变量并调用它:
var method = obj.func;
method();
Run Code Online (Sandbox Code Playgroud)
然后this会再次引用全局对象。在 JavaScript 中,函数就像任何其他值一样,它们与分配给它们的对象没有特殊关系。
var MyComponent = function(params)
{
setup.call(this, params); // <- using `call`
this.doSomething()
{
// doing something
};
function setup(params)
{
// Setup
// Interaction logic
var _this = this; // "this" to new created object
$(".some-element").click(function(){
_this.doSomething();
});
}
};
Run Code Online (Sandbox Code Playgroud)
或者在你的其他例子中:
var Item = function()
{
this.say = function()
{
alert("hello");
};
this.sayInternal = function()
{
_sayInternal.call(this);
};
function _sayInternal()
{
this.say();
};
};
Run Code Online (Sandbox Code Playgroud)
也就是说,这种将函数分配给对象的方法并不好,因为每个实例都有自己的 this.sayInternal函数。所以对于Item上面的代码,每次创建实例都涉及创建三个函数,这很浪费内存。
利用原型继承将是一个更好的方法:
var Item = function() {
};
Item.prototype = (function() {
function _sayInternal() {
this.say();
};
return {
say: function() {
alert("hello");
},
sayInternal: function(){
_sayInternal.call(this);
}
}
}());
Run Code Online (Sandbox Code Playgroud)
这样,_sayInternal只创建一次,所有实例都继承(引用)原型,因此say和sayInternal也只存在一次。带有立即函数的“技巧”使得_sayInternal只能通过say和访问sayInternal。