2012-08-16 2 views
0

지금까지 몇 번 실행했습니다. 나는 그것을 증명할 수있는 가장 간단한 코드 조각을 만들려고 노력했다.jquery "this"는 "this"객체에 대한 액세스를 금지합니다.

문제는 내부 및 개체 메서드입니다. 익명 함수를 jQuery 메서드 (예 : "each")에 함수의 내부로 전달하면 함수의 내부에서 "this"에 대한 액세스 권한을 잃게됩니다. "this"는 이제 jQuery 객체와 관련이 있기 때문입니다.

(. 내가 객체 리터럴로 정의 된 개체를 기반으로 개체 인스턴스를 생성하는 크록 포드의 객체 기능을 사용하고 있습니다)

:

문제의 핵심에 대한 logNameAndElementIds 방법의 중간에 주석을 참조하십시오

Object.create = function (o) { 
    function F() {} 
    F.prototype = o; 
    return new F(); 
}; 


var objectLiteral = { 

    setName: function(name){ 
     this.name = name; 
    }, 

    logNameAndElementIds: function(){ 

     // works fine, 'this' refers to object instance 
     console.log(this.name); 

     $('.foo').each(function(){ 

      // we've lost "this" because it now refers to jQuery 
      console.log(this.name); 
      console.log($(this).attr('id')); 
     }); 
    } 

}; 

obj1 = Object.create(objectLiteral); 
obj1.setName('Mike'); 
obj1.logNameAndElementIds(); 

이런 종류의 상황을 해결하거나 해결할 올바른 방법은 무엇입니까?

분명히 나의 예는 어리 석다. 그러나 그것은 단지 요점을 보여주기위한 것이다. 더 자주 jQuery와 일치하는 세트를 반복하고 각 항목에 포함 된 객체의 메소드를 호출하려고합니다. 하지만 jQuery의 "this"가 있기 때문에 객체의 메서드에 액세스 할 수 없습니다.

+0

은 당신이 알고 있습니까 기존 [Object.create] (https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create)를 덮어 쓰시겠습니까? – some

+0

자바 스크립트 IMHO의 함정 중 하나에 오신 것을 환영합니다. 밑줄이라는 외부 라이브러리를 사용하고 싶습니다. http://underscorejs.org/에서 확인하십시오. bind 함수는이 유형의 일에 특히 유용합니다. – Jlange

답변

0

은 내가 이전에 허용 된 것보다 이것에 더 나은 해답이 있다고 생각하고, 그 ES5의 새로운 Function.prototype.bind 방법을 사용하는 것입니다

당신의 logNameAndElementIds 기능을 찾고 있습니다. 훨씬 깨끗하며 모든 최신 브라우저에서 사용할 수 있으며 구형 브라우저에서 쉽게 사용할 수 있습니다.

바인드()이 같은 물건을 할 수와

:

var myObj = { 
    name: "Foo"; 

    iterateParagraphs: function() { 
     $("p").each(function(i,p){ 
      $(p).addClass("bar"); // use $(p) where you use to use $(this); 
      $(p).text(this.name); // this refers to myObj = Foo 
     }.bind(this)); // get this (myObj) into callback 
    } 
}; 

(주위에 최선을 것으로 보인다) 모질라 심의 축소 된 버전은 다음과 같습니다

Function.prototype.bind||(Function.prototype.bind=function(b){if("function"!==typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var d=Array.prototype.slice.call(arguments,1),e=this,a=function(){},c=function(){return e.apply(this instanceof a&&b?this:b,d.concat(Array.prototype.slice.call(arguments)))};a.prototype=this.prototype;c.prototype=new a;return c}); 
0

'포인터'값은 기능 블록의 범위에 따라 달라집니다.

var objectLiteral = { 

    setName: function(name){ 
     this.name = name; 
    }, 

    logNameAndElementIds: function(){ 

     // works fine, 'this' refers to object instance 
     console.log(this.name); 

     var self = this; 

     $('.foo').each(function(){ 

      //use 'self' instead of 'this' 

      console.log(self.name); 
      console.log($(this).attr('id')); 
     }); 
    } 

}; 
+0

.each()에서 "this"가 아닌 "self"를 사용하면 안됩니까? – starskythehutch

+0

@starskythehutch 나는 원래 코드를 수정하지 않았다. 아마도 그것을 바꿀 것이다. – nbrooks

0

이 알고있는 것 : 외부 범위 내에서 this를 참조하려면, 원래 개체 this의 사본을 (일반적인 규칙은 self로 저장되어있다)에 저장합니다. 보통 우리는 원래 this에 프록시를 사용합니다. 이 문제를 해결하기

var that = this; 
    $('.foo').each(function(){ 

     console.log(that); // original object 
     console.log(this); 


    }); 
1

방법은 새 범위 내에서 액세스 할 수있는 변수에 this을 저장하는 것입니다.

logNameAndElementIds: function(){ 

    // works fine, 'this' refers to object instance 
    console.log(this.name); 
    var that = this; 

    $('.foo').each(function(){ 

     // we've lost "this" because it now refers to jQuery 
     console.log(that.name); 
     console.log($(this).attr('id')); 
    }); 
} 
+0

그래, 이걸 얻지 만, 어색하고 기억이 집중되어서 이걸 복사 해 두지 않는다. 지역 변수에? 특히 많은 수의 객체 메소드에 대해 이렇게하면? 이것을 처리하는 더 우아한 방법이 없습니다. –

+0

.each.call (this, function() {/ * 여기에있는 내용을 여기에서 * 할 것입니다 * /}) 할 수 있도록 .call()을 컨텍스트를 지정할 수있는 곳에 항상 사용할 수 있습니다. – starskythehutch

+0

다소 어색합니다. 동의합니다. 그것이 범위가 자바 스크립트에서 작동하는 방법입니다. 메모리를 낭비한다는 측면에서 중요한 결과를 느끼지 않아야합니다. Javascript가 가비지 수집을 처리합니다. 내가 아는 한 외부 라이브러리를 사용하는 것 외에 다른 것을 처리하는 더 이상 우아한 방법이 없습니다. 누군가 밑줄을 썼습니다. 하지만 제 추측은 당신에게서 "못생긴"부분을 숨기는 것과 비슷한 것을하고 있다는 것입니다. 더 많은 JS gotcha가 있습니다. –

관련 문제