背景: 我的最新项目不能使用一个让我很难过的大型图书馆。我希望从任何库中获得一些东西,比如缺少的功能 addClass
, hasClass
, removeClass
,兼容 addEventListener
等等我创造了 一个小小的对象 在其他时间我想要一些意见,但是我在设置它时会遇到一些麻烦。
为方便使用, 我希望一个对象在创建时返回一个新的实例。
鉴于:
$ = function() {
this.name = "levi";
return this;
};
console.log($());
我们得到DOMWindow而不是 $
因为它的古怪性质 this
在JavaScript中。 对我来说更奇怪的是 console.log(new $().name)
正确地返回“levi”。如果 this
绑定到窗口,为什么对象正确获取值?。我们可以添加新的 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
它似乎在我的所有测试中都有效。
做你想做的最简单的方法是(我认为):
$ = function(){
if (!(this instanceof $)){
return new $;
}
this.name = 'levi';
return this;
}
刚回来的事实 this
不会因为这种方式而创建$的实例 this
创建执行 $
作为常规函数:在这种情况下的值 this
指向全局对象(在浏览器中: window
,实际上是在执行 $()
是相同的 window.$()
)。这可以说是javascript生活的事实。这个事实 console.log(new $().name)
显示正确的值是因为你将函数作为构造函数调用,它返回该构造函数的实例(即一个新的实例) $
)。但 console.log($().name)
还将打印'levi',因为它返回带有属性的全局对象 name
,即 window.name
。尝试 $(); console.log(name)
你会看到的 name
现在是一个全局变量。所以,如果你不想使用 new
每次关键字,检查您的函数是作为常规函数调用,还是作为实例的构造函数(=== instanceof $
)在构造函数中。使用上面的方法实例构造函数,无论它是否被实例化 new
总之是 $
也许你应该将问题的标题改为:'返回的对象[构造函数] 自己的一个例子“
也许 这篇博客文章 可以减轻光线。
jQuery的方式是首先测试是否 this
是 window
(称为函数),如果是,则返回自身的新实例。例如:
var $ = function() {
if(this === window) {
return new $();
}
this.name = "levi";
return this;
};
console.log($());
这是有效的,因为当您正常调用函数时(func()
) this
将与来电者相同 this
。 (相关但不相关: obj.method()
会有的 this
是 obj
)因为默认范围是 window
, this
内 $
将会 window
当你把它称为 $()
。
使用时调用函数 new
,会发生什么是JavaScript创建一个新对象,然后调用您的函数 this
设置为该对象。
此解决方案有效,因为它首先测试是否 this
是 window
因此被称为 $()
。如果它被称为 $()
,它会回来 new $()
。否则,它被称为 new $()
,并将按预期工作。
> $ = function() {
> this.name = "levi";
>
> return this; };
>
> console.log($());
我们得到DOMWindow而不是$
你打电话时 $ 作为一个功能,然后它 这个 关键字设置为全局对象,就像任何被调用的函数一样。
因为这个古怪的本质
在JavaScript中
JavaScript的 这个 关键字*按照指定的方式工作。它与其他语言不同,但这就是它的工作原理。
对我来说更奇怪的是
console.log($()。name)正确返回
“李维斯”。
你打电话时 $ 作为一种功能,它 这个 keyword是全局对象,因此:
this.name = 'levi';
创建一个名为的全局对象的属性 名称 价值'levi'。当你知道发生了什么事时并不奇怪。 :-)
我们可以添加新的console.log(新的
$()),它的工作原理。
这就是构造函数应该在javascript中调用的方式。调用函数时调用 新, 它的 这个 关键字设置为新构造的对象,所以 this.name
将创建该对象的新属性。顺便, return this
是多余的,建设者回归 这个 默认。
> $ = function() {
> var obj = function() {
> this.name = "levi";
> };
>
> return new obj(); };
的console.log($());这给了我什么
我想要,但似乎有点不必要
将对象包装在一个
创造它的功能。进一步
更多,它是obj类型而不是$
大概你正在使用 类型,只能返回ECMA-262指定的值之一。该短列表(包括对象,数字,字符串等)不包括 $。
这有什么其他方式
做了什么?
你可以使用你已经发现的方法,Lasse Reichstein Nielsen的克隆(也被Doublas Crockford推广为“beget”)和Richard Cornford的模块模式。使用Google,有很多很多关于以上所有内容的帖子。
尝试这样的事情:
function $(name){
if( !(this instanceof arguments.callee) ){
return new arguments.callee(name);
}
this.name = name;
return this;
}
更新:
@Levi Morrison
编辑:有没有人看到以下解决方案有任何问题:
既然你问过, 我并不完全爱上document.write。
试试这个:
var log = function(message){
if(message){
document.body.appendChild(document.createTextNode(message));
}
document.body.appendChild(document.createElement('br'));
}