이것은 JavaScript에서 비교적 유연하며, 환경에 따라 또는 동일한 함수가 다른 방식으로 호출되는 경우에 달라질 수 있습니다. 하지만 라는 일반적인 원칙이 있습니다. 즉, 함수를 호출하는 객체를 가리킨다는 것입니다.
JavaScript의 클로저(Closure)에 대한 심층 소개
-JavaScript의 심층 소개
JavaScript의 프로토타입 체인 및 상속에 대한 심층 소개
다음은 제가 공부한 노트입니다. 8가지 상황으로 나열되어 있습니다.
전역 범위에서 이는 일반적으로 브라우저의 창인 전역 객체를 가리킵니다. , 이 개체는 전역 개체입니다.
console.log(this.document === document); // true (document === window.document) console.log(this === window); // true this.a = 37; //相当于创建了一个全局变量a console.log(window.a); // 37
일반 함수 선언 또는 함수 표현식입니다. 함수가 직접 호출되는 경우에도 브라우저에서는 이 객체가 전역 객체를 가리킵니다. 창. 노드에서 이 개체는 전역 개체입니다.
function f1(){ return this; } f1() === window; // true, global object
또 다른 예를 들어보면 읽어보면 매우 명확해질 것입니다.
function test(){ this.x = 1; alert(this.x); } test(); // 1
이것이 전역 개체임을 증명하려면 코드를 일부 변경하세요.
var x = 1; function test(){ alert(this.x); } test(); // 1
실행 결과는 여전히 1입니다. 다시 변경하세요:
var x = 1; function test(){ this.x = 0; } test(); alert(x); //0
그러나 엄격 모드에서 일반 함수가 호출되면 이는 정의되지 않음을 가리키며, 이것이 노드가 엄격 모드를 사용하는 이유 중 하나입니다.
function f2(){ "use strict"; // see strict mode return this; } f2() === undefined; // true
객체 메소드로 사용하는 것이 일반적입니다.
다음 예에서는 객체 리터럴 o를 만듭니다. o에 속성 f가 있습니다. 그 값은 함수 객체입니다. 객체의 메소드로 호출되면 o
var o = { prop: 37, f: function() { return this.prop; } }; console.log(o.f()); // logs 37
객체를 가리킨다. 함수 리터럴처럼 반드시 객체를 정의할 필요는 없다. independent() 함수가 직접 호출되면 이는 창을 가리킬 것이지만 할당을 통해 일시적으로 속성 f를 만들고 함수 개체를 가리킬 때 여전히 37을 얻습니다.
var o = {prop: 37}; function independent() { return this.prop; } o.f = independent; console.log(o.f()); // logs 37
그래서 함수가 어떻게 만들어지든 상관은 없지만 함수가 객체의 메서드로 호출되는 한 이것은 객체를 가리킬 것입니다.
다음 예에서는 먼저 속성 f와 함수가 있는 객체 o를 만듭니다. 객체 속성의 값으로 Object.create(o)를 통해 객체 p를 생성합니다. p는 빈 객체이고 해당 프로토타입은 o를 가리킨 다음 p.a = 1을 사용하여 속성을 생성합니다. 프로토타입에서 메소드 this.a, this.b를 호출하면 여전히 객체 p에서 a와 b를 얻을 수 있습니다. 여기서 주목해야 할 점은 p의 프로토타입이 o라는 것입니다. p.f()를 호출하면 프로토타입 체인에서 f 속성을 호출하여 현재 객체 p를 얻을 수 있습니다.
var o = {f:function(){ return this.a + this.b; }}; var p = Object.create(o); p.a = 1; p.b = 4; console.log(p.f()); // 5
는 일반적으로 생성자의 get/set 메소드
function modulus(){ return Math.sqrt(this.re * this.re + this.im * this.im); } var o = { re: 1, im: -1, get phase(){ return Math.atan2(this.im, this.re); } }; Object.defineProperty(o, 'modulus', { //临时动态给o对象创建modules属性 get: modulus, enumerable:true, configurable:true}); console.log(o.phase, o.modulus); // logs -0.78 1.4142
new를 사용하여 MyClass를 생성자로 호출하면 this는 빈 개체를 가리키고 이 개체의 프로토타입은 MyClass.prototype을 가리킵니다(프로토타입 체인 요약은 이 문서 참조). , 그러나 호출 당시 this.a = 37 의 할당이 이루어졌으므로 결국 this 를 반환 값으로 사용하게 됩니다(return 문을 작성하지 않거나 return이 기본형인 경우 this 두 번째 예에서는 return 문이 객체를 반환하고 a = 38이 반환 값으로 사용됩니다
function MyClass(){ this.a = 37; } var o = new MyClass(); console.log(o.a); // 37 function C2(){ this.a = 37; return {a : 38}; } o = new C2(); console.log(o.a); // 38
다양한 호출 방법 외에도 함수 개체의 일부 메서드는 호출/적용과 같은 함수 실행을 수정할 수 있습니다.
call이 매개변수를 플랫 방식으로 전달하는 반면 Apply는 배열을 전달한다는 점을 제외하면 호출과 적용 사이에는 기본적으로 차이가 없습니다. 아래 예시
언제 전화상담 및 신청을 해야 하나요? 예를 들어 Object.prototype.toString을 호출하고 싶지만 특정 this를 지정하려는 경우 Object.prototype.toString.call(this)을 사용하여 직접 호출할 수 없는 메서드를 호출할 수 있습니다. 다음 예를 들어보세요.
function add(c, d){ return this.a + this.b + c + d; } var o = {a:1, b:3}; add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16 //第一个参数接收的是你想作为this的对象 add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34 function bar() { console.log(Object.prototype.toString.call(this)); } bar.call(7); // "[object Number]"
bind 메소드는 es5부터 제공되므로 ie9+는
function f(){ return this.a; } var g = f.bind({a : "test"}); //想把某个对象作为this的时候,就把它传进去,得到一个新对象g console.log(g()); // test //重复调用的时候,this已经指向bind参数。这对于我们绑定一次需要重复调用依然实现绑定的话,会比apply和call更加高效(看下面这个例子) var o = {a : 37, f : f, g : g}; console.log(o.f(), o.g()); // 37, test //o.f()通过对象的属性调用,this指向对象o;比较特殊的是即使我们把新绑定的方法作为对象的属性调用,o.g()依然会按之前的绑定去走,所以答案是test不是g
만 지원합니다. 프로젝트 그제서야 이러한 기본 개념이 얼마나 중요한지 깨달았습니다. 하나씩 구현하지 않으면 정말 우연히 함정에 빠질 것입니다. 앞으로는 프로토타입 체인, 범위, 상속, 체인 호출, 규칙성 및 기타 지식도 요약할 것입니다. 팔로우를 환영합니다
위 내용은 JavaScript로 자세히 설명되어 있습니다. PHP 중국어 넷(www.php.cn)에 주목하세요!