JavaScript에서 흥미로운 상황이 발생했습니다. 객체 리터럴 표기법을 사용하여 여러 객체를 정의하는 메소드가있는 클래스가 있습니다. 해당 개체 내에서 this
포인터가 사용 중입니다. 프로그램의 동작에서, this
포인터가 리터럴에 의해 생성되는 객체가 아니라 메소드가 호출 된 클래스를 참조 한다고 추론했습니다 .
이것이 내가 예상하는 방식이지만 임의적 인 것처럼 보입니다. 이것이 정의 된 동작입니까? 브라우저 간 안전한가요? 그것이 “사양이 말하는 것”이외의 이유가 무엇인지에 대한 근거가 있습니까? 파싱 된 코드 예제 :
// inside class definition, itself an object literal, we have this function:
onRender: function() {
this.menuItems = this.menuItems.concat([
{
text: 'Group by Module',
rptletdiv: this
},
{
text: 'Group by Status',
rptletdiv: this
}]);
// etc
}
답변
내 다른 게시물에서 식인종 처리되었습니다. 여기에 대해 알고 싶은 것 이상 이 있습니다.
시작하기 전에 Javascript에 대해 명심하고 이해가되지 않을 때 자신에게 반복하는 것이 가장 중요합니다. Javascript에는 클래스가 없습니다 (ES6 class
은 구문 설탕입니다 ). 어떤 것이 수업처럼 보인다면 영리한 속임수입니다. Javascript에는 객체 와 함수가 있습니다. (그것은 100 % 정확하지는 않지만 함수는 객체 일뿐이지만 때로는 별도의 것으로 생각하면 도움이 될 수 있습니다)
이 변수 함수에 부착된다. 당신이 함수를 호출 할 때마다, 이 방법 함수 호출에 따라 특정 값이 부여됩니다. 이것을 종종 호출 패턴이라고합니다.
자바 스크립트에서 함수를 호출하는 방법에는 네 가지가 있습니다. 당신은 같은 함수를 호출 할 수있는 방법 A와, 기능 A와, 생성자 와 함께하는 것은 적용 .
방법으로
메소드는 객체에 첨부 된 함수입니다
var foo = {};
foo.someMethod = function(){
alert(this);
}
방법으로 호출되면, 이는 기능 / 방법의 일부 객체에 바인딩한다. 이 예에서는 foo에 바인딩됩니다.
기능으로
독립형 함수가있는 경우, 이 변수는 “글로벌”객체, 브라우저의 컨텍스트에서 거의 항상 창 객체에 바인딩됩니다 .
var foo = function(){
alert(this);
}
foo();
이것은 당신을 방해하는 것일 수도 있지만 나쁘지 않습니다. 많은 사람들이 이것을 나쁜 설계 결정으로 생각합니다. 콜백은 메소드가 아닌 함수로 호출되기 때문에 일관성이없는 것으로 보이는 이유가 표시됩니다.
많은 사람들이 이런 식으로 문제를 해결합니다.
var foo = {};
foo.someMethod = function (){
var that=this;
function bar(){
alert(that);
}
}
this 를 가리키는 변수 를 정의합니다 . 클로저 (자체 주제)는 그 주위를 유지 하므로 콜백으로 bar를 호출하면 여전히 참조가 있습니다.
참고 : use strict
기능으로 사용되는 모드 에서는 this
전역에 바인딩되지 않습니다. (입니다 undefined
).
생성자로서
함수를 생성자로 호출 할 수도 있습니다. (TestObject)를 사용하는 이름 지정 규칙을 기반으로 이것은 또한 수행중인 작업 일 수도 있고 걸려 넘어지는 작업 일 수도 있습니다 .
새 키워드를 사용하여 생성자로 함수를 호출합니다.
function Foo(){
this.confusing = 'hell yeah';
}
var myObject = new Foo();
생성자로 호출하면 새로운 객체가 생성되고, 이것은 그 개체에 바인딩됩니다. 당신이 내부 기능을 가지고 그들이 콜백으로 사용하는 경우 다시 말하지만, 당신은 함수로 호출 할 것이고, 이것은 전역 객체에 바인딩됩니다. 그 var that = this trick / pattern을 사용하십시오.
어떤 사람들은 생성자 / 새 키워드가 클래스와 비슷한 것을 만드는 방법으로 Java / 전통 OOP 프로그래머에게 던져진 뼈라고 생각합니다.
Apply 방법으로
마지막으로 모든 함수에는 “apply”라는 메소드가 있습니다 (예, 함수는 Javascript의 객체 임). Apply를 사용하면 이 값 이 무엇인지 결정할 수 있으며 인수 배열을 전달할 수도 있습니다. 쓸모없는 예가 있습니다.
function foo(a,b){
alert(a);
alert(b);
alert(this);
}
var args = ['ah','be'];
foo.apply('omg',args);
답변
함수 호출
함수는 단지 일종의 객체입니다.
모든 Function 객체에는 호출 된 Function 객체 를 실행하는 호출 및 적용 메소드가 있습니다.
이 메소드에 대한 첫 번째 인수 this
는 함수를 실행하는 동안 키워드 가 참조 할 오브젝트를 지정합니다. null
또는 undefined
오브젝트 인 경우 전역 오브젝트 window
가에 사용됩니다 this
.
따라서 함수를 호출하면 …
whereAmI = "window";
function foo()
{
return "this is " + this.whereAmI + " with " + arguments.length + " + arguments";
}
… 괄호 – foo()
– 동등 foo.call(undefined)
또는 foo.apply(undefined)
인 효과적으로 동일 foo.call(window)
하거나 foo.apply(window)
.
>>> foo()
"this is window with 0 arguments"
>>> foo.call()
"this is window with 0 arguments"
추가 인수 call
는 함수 호출에 인수로 전달되는 반면 단일 추가 인수 apply
는 함수 호출에 대한 인수를 Array와 같은 객체로 지정할 수 있습니다.
따라서, foo(1, 2, 3)
동등 foo.call(null, 1, 2, 3)
하거나 foo.apply(null, [1, 2, 3])
.
>>> foo(1, 2, 3)
"this is window with 3 arguments"
>>> foo.apply(null, [1, 2, 3])
"this is window with 3 arguments"
함수가 객체의 속성 인 경우 …
var obj =
{
whereAmI: "obj",
foo: foo
};
… 목적에 따라 기능에 대한 참조에 액세스 괄호로 호출 – obj.foo()
– 동등 foo.call(obj)
하거나 foo.apply(obj)
.
그러나 객체의 속성으로 유지되는 함수는 해당 객체에 “바인드”되지 않습니다. obj
위 의 정의에서 볼 수 있듯이 함수는 객체 유형일 뿐이므로 참조 할 수 있습니다 (따라서 함수 호출에 대한 참조로 전달되거나 함수 호출에서 참조로 반환 될 수 있음). 함수에 대한 참조가 전달 될 때, 그것이 전달에 대한 추가 정보 에서 입니다 그것으로 수행되고, 다음과 같은 변화가 없습니다 이유 :
>>> baz = obj.foo;
>>> baz();
"this is window with 0 arguments"
함수 참조 baz
에 대한 호출은 호출에 대한 컨텍스트를 제공하지 않으므로 효과적으로와 동일 baz.call(undefined)
하므로 this
참조 window
합니다. 우리가 원하는 경우 baz
가에 속한다는 것을 알고 obj
, 우리가 어떻게 든 그 정보를 제공 할 필요가 baz
있다라고를 위치로 첫 번째 인수 call
또는 apply
폐쇄가 활동하기 시작합니다.
스코프 체인
function bind(func, context)
{
return function()
{
func.apply(context, arguments);
};
}
함수가 실행되면 새 범위가 만들어지고 모든 범위에 대한 참조가 있습니다. 위의 예제에서 익명 함수를 만들면 해당 함수가 만들어진 범위 (의 범위)에 대한 참조가 bind
있습니다. 이것을 “클로저”라고합니다.
[global scope (window)] - whereAmI, foo, obj, baz
|
[bind scope] - func, context
|
[anonymous scope]
변수에 액세스하려고 할 때이 “범위 체인”은 주어진 이름을 가진 변수를 찾기 위해 안내됩니다. 현재 범위에 변수가 포함되어 있지 않으면 체인의 다음 범위를 확인합니다. 글로벌 범위. 익명 함수가 반환되고 bind
실행이 완료 되면 익명 함수는 여전히 bind
범위에 대한 참조를 가지 므로 bind
범위가 “이탈”되지 않습니다.
위의 모든 사항을 감안할 때 이제 다음 예제에서 범위가 작동하는 방식과 특정 값으로 “사전 바인딩 된”함수를 전달하는 기술이 작동이라고하는 이유를 이해할 수 this
있습니다.
>>> baz = bind(obj.foo, obj);
>>> baz(1, 2);
"this is obj with 2 arguments"
답변
이것이 정의 된 동작입니까? 브라우저 간 안전한가요?
예. 그리고 그렇습니다.
그것이 왜 그런지에 대한 근거가 있습니까?
그 의미 this
추론하기 매우 간단합니다.
- 경우
this
생성자 함수 내에서 사용되며, 함수가 호출 된new
키워드this
생성 될 객체를 참조합니다.this
공개 메소드에서도 객체를 계속 의미합니다. this
중첩 된 보호 기능을 포함하여 다른 곳에서 사용되는 경우 전역 범위 (브라우저의 경우에는 창 개체)를 가리 킵니다.
두 번째 경우는 분명히 디자인 결함이지만 클로저를 사용하여 해결하기가 쉽습니다.
답변
이 경우 내부 this
는 this
외부 함수 의 변수 대신 전역 객체에 바인딩됩니다 . 언어가 설계된 방식입니다.
자세한 설명은 Douglas Crockford의 “자바 스크립트 : 좋은 부분”을 참조하십시오.
답변
ECMAScript 에 대한 훌륭한 자습서를 찾았습니다.
이 값은 실행 컨텍스트와 관련된 특수 객체입니다. 따라서 컨텍스트 객체 (즉, 컨텍스트가 실행 컨텍스트가 활성화 된 객체)로 명명 될 수 있습니다.
컨텍스트의이 값으로 모든 개체를 사용할 수 있습니다.
이 값은 실행 컨텍스트의 속성이지만 변수 객체의 속성은 아닙니다.
변수와 달리이 값은 식별자 확인 프로세스에 참여하지 않기 때문에이 기능은 매우 중요합니다. 즉, 코드 에서이 코드에 액세스하면 해당 값은 실행 컨텍스트에서 직접 가져오고 범위 체인 조회가 없습니다. 이 값은 컨텍스트를 입력 할 때 한 번만 결정됩니다.
글로벌 컨텍스트에서이 값은 글로벌 오브젝트 자체입니다 (즉,이 값은 가변 오브젝트와 같습니다).
함수 컨텍스트의 경우 모든 단일 함수 호출에서이 값이 다를 수 있습니다
참조 자바 스크립트 – 더 – 코어 및 장-3이