자신의 인스턴스를 반환하는 객체
-
09-09-2020 - |
문제
배경: 내 최근 프로젝트에서는 대규모 라이브러리를 사용할 수 없어서 안타깝습니다.누락된 함수와 같이 모든 라이브러리에서 갖고 싶은 몇 가지 사항이 있습니다. addClass
, hasClass
, removeClass
, 호환 가능 addEventListener
, 등.그래서 내가 만들었어요 작은 물건 나중에 의견을 듣고 싶지만 원하는 대로 설정하는 데 약간의 어려움이 있습니다.
이용편의를 위해, 나는 객체가 생성될 때 자신의 새로운 인스턴스를 반환하기를 원합니다.
주어진:
$ = function() {
this.name = "levi";
return this;
};
console.log($());
대신 DOMWindow를 얻습니다. $
그 특이한 성격 때문에 this
자바스크립트에서. 나에게 더 이상한 점은 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.$()
).말하자면 그것은 자바스크립트 생활의 사실입니다.사실 그 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
BE obj
) 기본 범위는 다음과 같습니다. window
, this
내부에 $
될거야 window
당신이 그것을 다음과 같이 부를 때 $()
.
다음을 사용하여 함수를 호출할 때 new
, JavaScript가 새 객체를 생성한 다음 다음을 사용하여 함수를 호출하면 어떻게 되나요? this
해당 개체로 설정합니다.
이 솔루션은 다음을 먼저 테스트하기 때문에 작동합니다. this
~이다 window
, 따라서 다음과 같이 호출되었습니다. $()
.만약 그것이 다음과 같이 불렸다면 $()
, 돌아올 것이다 new $()
.그렇지 않으면 다음과 같이 호출되었습니다. new $()
, 예상대로 작동합니다.
> $ = function() {
> this.name = "levi";
>
> return this; };
>
> console.log($());
$ 대신 DOMWindow를 얻습니다.
당신이 전화할 때 $ 기능적으로는 이것 키워드는 그런 식으로 호출되는 모든 함수와 마찬가지로 전역 객체로 설정됩니다.
JavaScript에서 이것의 기발한 특성 때문에
자바스크립트의 이것 키워드*는 작동하도록 지정된 대로 작동합니다.다른 언어와는 다르지만 그것이 작동하는 방식입니다.
나에게 더 이상한 것은 Console.log ($ (). name)이 "levi"를 올바르게 반환한다는 것입니다.
당신이 전화할 때 $ 함수로서, 이것 키워드는 전역 개체이므로 다음과 같습니다.
this.name = 'levi';
라는 전역 객체의 속성을 생성합니다. 이름 값은 'levi'입니다.무슨 일이 일어나고 있는지 알면 이상하지 않습니다.:-)
우리는 단지 새로운 콘솔을 추가 할 수 있습니다 (new $ ()).
이것이 자바스크립트에서 생성자를 호출하는 방식입니다.함수가 호출될 때 새로운, 그것은 이것 키워드는 새로 생성된 객체로 설정되므로 this.name
해당 개체의 새 속성을 만듭니다.그런데, return this
중복되고 생성자가 반환됩니다. 이것 기본적으로.
> $ = function() {
> var obj = function() {
> this.name = "levi";
> };
>
> return new obj(); };
console.log($());그것은 내가 원하는 것을 제공하지만, 그것을 생성하는 함수 내부의 객체를 감싸는 것은 약간 불필요한 것 같습니다.더욱
아마도 당신은 유형, 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;
}
업데이트:
@레비 모리슨
편집하다:다음 해결 방법에 문제가 있는 사람이 있습니까?
물어보셨기 때문에, 나는 document.write를 별로 좋아하지 않는다..
대신 이것을 시도해 보세요:
var log = function(message){
if(message){
document.body.appendChild(document.createTextNode(message));
}
document.body.appendChild(document.createElement('br'));
}