Javascript 向对象添加方法
在用JS编写了一段时间之后,我决定创建自己的框架。类似于jQuery的东西。但是一个非常精简的版本。在谷歌搜索之后,我整理了以下代码:Javascript 向对象添加方法,javascript,function,object,methods,Javascript,Function,Object,Methods,在用JS编写了一段时间之后,我决定创建自己的框架。类似于jQuery的东西。但是一个非常精简的版本。在谷歌搜索之后,我整理了以下代码: function $elect(id) { if (window === this) { return new $elect(id); } this.elm = document.getElementById(id); } $elect.prototype = { hide: function () { th
function $elect(id) {
if (window === this) {
return new $elect(id);
}
this.elm = document.getElementById(id);
}
$elect.prototype = {
hide: function () { this.elm.style.display = 'none'; },
show: function () { this.elm.style.display = ''; },
toggle: function ()
{
if (this.elm.style.display !== 'none') {
this.elm.style.display = 'none';
} else {
this.elm.style.display = '';
}
}
};
到目前为止,这似乎是可行的。但我对功能不感兴趣。我想了解逻辑。添加方法部分是可以理解的。虽然我不明白
if (window === this) {
return new $elect(id);
}
如果我删除它,函数将中断。因为这是一个if语句,所以有两个结果<代码>真或假
。所以我尝试删除if语句,只使用返回新的$elect(id)代码>假设窗口===此
返回真
,但不起作用。然后我认为它可能返回false
,所以删除了整个if语句。那也没用。有人能启发我吗?这个代码也有效吗?我可能遗漏了一些东西
只是在jsfiddle上测试了一下,它不起作用。虽然它对jsbin o.o.有效
编辑:使用$elect(id).toggle()代码>来调用它。尽管您可以查看演示。此逻辑:
if (window === this) {
return new $elect(id);
}
确保在构造函数作为函数调用时:
var foo = $elect(id);
而不是作为构造器:
var fo = new $elect(id);
它将返回正确的结果-一个新的$elect对象。当作为函数调用时,在浏览器中运行时,默认上下文将是全局上下文或窗口
,触发if
子句并返回作为构造函数调用它的结果
为什么它在你的小提琴中不起作用
在链接的fiddle中,设置为将代码包装在onload
处理程序中。其结果如下所示:
window.onload=function(){
function $elect(id) {
if (window === this) {
return new $elect(id);
}
this.elm = document.getElementById(id);
}
$elect.prototype = {
hide: function () { this.elm.style.display = 'none'; },
show: function () { this.elm.style.display = ''; },
toggle: function ()
{
if (this.elm.style.display !== 'none') {
this.elm.style.display = 'none';
} else {
this.elm.style.display = '';
}
}
};
}
$elect("theId").hide();
var bob = {};
bob.$select("theId").hide();
因此,您的$elect
变量在onload
处理程序范围之外不可见
通常,您希望向全局范围添加一个变量,以便能够访问您的框架。在上述代码末尾添加类似的内容将使其可见:
window.$elect = $elect;
我想了解逻辑
$elect
是应使用(new$select
)调用的。如果不是($elect()
),那么会发生什么?没有构造实例,并且将指向全局对象(窗口
)——这是我们不想要的。因此,当这个代码段检测到它使用new
正确地调用自己并返回时,它可以防止这种情况
如果我删除它,函数将中断
当您在没有保护的情况下像调用$elect(id)
那样调用它时,它将向全局对象(本质上是一个全局变量)添加一个elm
属性,并且不返回任何内容。尝试调用上的.toggle()
方法将产生异常undefined没有方法“toggle”
我试图删除if语句,假设window==this
返回true
那么,您刚刚创建了一个无限递归函数,它在调用时会导致堆栈溢出异常
顺便说一句,不是要与窗口
(全局对象在非浏览器环境中可能有不同的名称)进行比较,而是要检查正确的继承。您希望构造函数仅应用于“类”的实例,即继承自$elect.prototype
的对象。例如,当使用new
调用时,可以保证这一点。要执行该检查,您将使用:
这也使得防护的意图更加明确。首先要了解的是,此函数正在调用自身:
function $elect(id) {
if (window === this) {
return new $elect(id);
}
this.elm = document.getElementById(id);
}
第一次调用函数窗口的时间是===this。因为在这里,您将函数作为方法调用。当作为方法调用时,函数将绑定到函数/方法所属的对象。在本例中,此
将绑定到窗口,即全局范围
但是,使用new
关键字,您将作为构造函数调用函数。当作为构造函数调用时,将创建一个新对象,并且此
将绑定到该对象,因此此
不再第二次引用窗口
对于$elect的新实例,您还可以将局部变量elm正确设置为该实例,允许其他函数稍后调用该elm。您的函数是一个构造函数。默认情况下,未在任何其他对象上显式调用的任何函数($elect()
,而非foo.$elect()
)中的this
)中的this
将作为方法传递给全局对象(窗口)。但是,if
检查如果此
确实引用了窗口
对象,返回新的$elect(id)代码>被执行。新的$elect(id)
执行以下操作:
- 创建
$elect.prototype的新实例
- 将新创建的实例放入
this
中,然后再次调用该方法
在第二步中,this===window
的计算结果为false
要了解该条件是如何工作的,您必须首先知道,在全局范围中,this
指的是window
对象。在局部范围内,例如在对象内,此
指的是对象本身
$elect
函数是框架的构造函数。如果你直接这样称呼它:
$elect('some-id-blah')
它将首先意识到您正在尝试创建一个实例(因为条件window===this
将计算为true),并且它将递归地创建自己的一个新实例。一旦这样做,此
将不再引用窗口
对象,它将引用库的新实例,因此该条件将不满足
我希望这可以理解。如果你这样称呼的话
return new $elect("theId")
var bob = {};
bob.$select("theId").hide();
$elect('theId').show().red();