Javascript 返回自身实例的对象

Javascript 返回自身实例的对象,javascript,library-design,Javascript,Library Design,背景:我的最新项目无法使用大型库,这让我很难过。我想从任何库中获得一些东西,比如缺少的函数addClass,hasClass,removeClass,compatibleaddEventListener,等等。所以我创建了它,我希望在其他时间能得到一些意见,但我在设置它时遇到了一些麻烦 为便于使用,我希望对象在创建时返回其自身的新实例。 鉴于: $ = function() { this.name = "levi"; return this; }; console.log(

背景:我的最新项目无法使用大型库,这让我很难过。我想从任何库中获得一些东西,比如缺少的函数
addClass
hasClass
removeClass
,compatible
addEventListener
,等等。所以我创建了它,我希望在其他时间能得到一些意见,但我在设置它时遇到了一些麻烦

为便于使用,我希望对象在创建时返回其自身的新实例。

鉴于:

 $ = function() {
    this.name = "levi";

    return this;
};

console.log($());
我们使用DOMWindow而不是
$
,这是因为JavaScript中
这个
的古怪特性。更奇怪的是,
console.log(new$().name)
正确地返回“levi”。如果
绑定到窗口,为什么对象正确获取了值?。我们只需添加新的
console.log(new$())
就可以了。然而,我不想每次都写新的。所以我试着:

$ = function() {
    var obj = function() {
        this.name = "levi";
    };

    return new obj();
};

console.log($());
这给了我想要的东西,但似乎没有必要将对象封装在创建它的函数中。此外,返回的对象是
obj
,而不是
$
。比较测试将失败

还有什么其他方法可以做到这一点?有没有更优雅的解决方案?我毫不犹豫地重新思考我的整个过程。我认为自己很擅长使用JavaScript,但是创建新的JavaScript是我很陌生的事情。
有人认为以下解决方案有什么问题吗

$a = function() {};

$ = function() {
    if (!(this instanceof $)) {
        return new $();
    }

    this.name = "levi";

    return this;
};

//helper function
var log = function(message) {
    document.write((message ? message : '') + "<br/>");
};

log("$().name == window.name: " + ($().name == window.name)); //false
log("$().name: " + $().name); //levi
log("window.name: " + window.name); //result

log();

log("$a instanceof $: " + ($a instanceof $)); //false
log("typeof $a: " + (typeof $a)); //function
log("typeof $: " + (typeof $)); //function
$a=function(){};
$=函数(){
如果(!(此实例为$){
返回新的$();
}
this.name=“levi”;
归还这个;
};
//辅助函数
变量日志=函数(消息){
编写((消息?消息:“”)+“
”); }; 日志(“$().name==window.name:”+($().name==window.name))//假的 日志(“$().name:”+$().name)//利维 日志(“window.name:+window.name”)//结果 log(); 日志(“$a instanceof$:”+($a instanceof$)//假的 日志(“类型$a:”+(类型$a))//功能 日志(“typeof$:”+(typeof$)//功能

它似乎在我所有的测试中都起作用

jQuery的方法是首先测试
这个
是否是
窗口
(作为函数调用),如果是,则返回自身的新实例。例如:

var $ = function() {
    if(this === window) {
        return new $();
    }
    this.name = "levi";
    return this;
};

console.log($());
这是因为当您正常调用函数(
func()
)时,
将与调用方的
相同。(相关但并非无关:
obj.method()
将具有
obj
),因为默认范围是
窗口
当您将其称为
$
时,此
内部的
将是
窗口

当您使用
new
调用函数时,发生的情况是JavaScript创建一个新对象,然后在
this
设置为该对象的情况下调用您的函数

此解决方案之所以有效,是因为它首先测试此
是否为
窗口
,因此被称为
$()
。如果像
$()
那样调用它,它将返回
new$()
。否则,它将使用
new$()
调用,并将按预期工作

>  $ = function() {
>     this.name = "levi";
> 
>     return this; };
> 
> console.log($());
我们得到的是一个窗口而不是一个窗口$

当您将$作为function调用时,它的this关键字将被设置为全局对象,就像任何这样调用的函数一样

因为这种奇怪的性质 在JavaScript中

Javascript的this关键字*按照指定的方式工作。它与其他语言不同,但这就是它的工作原理

对我来说更奇怪的是 console.log($().name)正确返回 “李维”

将$作为函数调用时,其this关键字是全局对象,因此:

this.name = 'levi';
创建名为name的全局对象的属性,其值为“levi”。当你知道发生了什么时并不奇怪。:-)

我们可以添加新的console.log(新的 $())并且有效

这就是在javascript中调用构造函数的方式。当使用new调用函数时,其this关键字设置为新构造的对象,因此
this.name
将创建该对象的新属性。顺便说一句,
返回这个
是多余的,构造函数默认返回这个

> $ = function() {
>     var obj = function() {
>         this.name = "levi";
>     };
> 
>     return new obj(); };
console.log($());这给了我什么 我想要,但似乎有点不必要 将对象包裹在 创建它的函数。进一步的 更重要的是,它是obj型而不是$

假设您使用的是typeof,它只能返回ECMA-262指定的一个值。该短列表(包括对象、数字、字符串等)不包括$

还有什么其他的方法 完成了吗


您可以使用您已经发现的方法,Lasse Reichstein Nielsen的克隆(Doublas Crockford也将其称为“beget”)和Richard Cornford的模块模式。使用谷歌,有很多关于以上所有内容的帖子。

试试这样的方式:

function $(name){
    if( !(this instanceof arguments.callee) ){
        return new arguments.callee(name);
    }
    this.name = name;
    return this;
}
更新

@李维莫里森

编辑:是否有人发现以下解决方案有任何问题:

自从你问起,。
请尝试以下方法:

var log = function(message){
    if(message){
        document.body.appendChild(document.createTextNode(message));
    }
    document.body.appendChild(document.createElement('br'));
}

做你想做的事情最简单的方法是(我认为):

仅仅返回
this
并不会创建$instance,这是因为
this
是作为常规函数执行
$
而创建的:在这种情况下,
this
的值指向全局对象(在浏览器中:
窗口
,实际调用executing
$()
窗口相同。$()
)。可以说,这是javascript生活的一个事实。
console.log(new$().name)
显示正确的值是因为您将函数作为构造函数调用,它返回该构造函数的实例(即
$
的新实例)。但是
console.log($().name)$ = function(){
    if (!(this instanceof $)){
     return new $;
    }
    this.name = 'levi'; 
    return this;
}