Javascript 向对象添加方法

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

在用JS编写了一段时间之后,我决定创建自己的框架。类似于jQuery的东西。但是一个非常精简的版本。在谷歌搜索之后,我整理了以下代码:

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();