>  기사  >  웹 프론트엔드  >  Javascript에서 이것의 사용법에 대한 자세한 설명

Javascript에서 이것의 사용법에 대한 자세한 설명

不言
不言앞으로
2019-03-23 09:36:422442검색

이 글은 Javascript에서의 사용법에 대한 자세한 설명을 제공합니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.

Javascript를 이해하기 전에 먼저 범위를 이해하세요.

범위는 두 가지 유형으로 나뉩니다.

1. 어휘 범위: 엔진은 현재 범위 또는 중첩된 하위 범위에서 이름 식별자가 있는 변수를 찾습니다. (엔진이 검색하는 방법과 위치. 정의 프로세스는 코드 작성 단계에서 발생합니다.)
2. 동적 범위: 범위는 런타임에 동적으로 결정됩니다.

어휘 범위와 동적 범위의 차이점은 다음과 같습니다. 어휘 범위는 코드나 정의를 작성할 때 결정됩니다. 동적 범위는 런타임에 결정됩니다.

this

this의 바인딩 규칙은 함수 호출 위치에 따라 호출될 때 바인딩됩니다. 이를 통해 우리는 일반적인 상황(엄격하지 않은 모드)에서 함수 호출(호출 스택)의 컨텍스트에 따라 객체를 바인딩한다는 것을 알 수 있습니다.

1. 기본 바인딩

기본 바인딩: 기본 바인딩은 엄격하지 않은 모드에서 다른 바인딩 규칙을 사용하지 않고 함수 호출(호출 스택) 개체의 컨텍스트에 따라 개체(전역)를 바인딩하는 것을 의미합니다. (엄격 모드에서는 undefound가 바인딩됩니다)

예:

function foo() {
    console.log(this.a);
};
function bar() {
    var a = 3;
    foo();
}
var a = 2;
bar();  //调用栈在全局作用域,this绑定全局对象

运行结果为: 2
//加上"use strict"运行结果则会变成this is undefined

여기서 함수가 호출되면 기본 바인딩이 사용됩니다. 함수 호출(호출 스택)의 컨텍스트는 전역 범위이므로 다음과 같이 바인딩됩니다. 전역 개체.

eg2:
function foo() {
    console.log(this.a)
};
var a = 2;
(function() {
    "use strict"
    foo();
})();

运行结果为: 2

여기에 주목해야 합니다: 기본 바인딩의 경우 이 바인딩 개체를 결정하는 것은 호출 위치가 엄격 모드에 있는지 여부가 아니라 함수 본문이 엄격 모드에 있는지 여부입니다(함수 본문이 엄격 모드에 있으면 이 바인딩은 정의되지 않습니다. 그렇지 않으면 이 바인딩 전역 개체입니다. 추가: Strict 모드와 Non-Strict 모드를 바인딩하는 것이 가능하지만 혼합하지 않는 것이 가장 좋습니다.

간접 참조는 일반적으로 기본 바인딩 규칙을 적용합니다.

eg:
function foo() {
    console.log(this.a);
};
var a = 2;
var o = { a: 3, foo: foo };
var p = { a: 4 };
o.foo();   //3
(p.foo = o.foo)();  //2

대입 표현식 p.foo = o.foo의 반환 값은 대상 함수 foo를 직접 참조합니다.

2. 암시적 바인딩

암시적 바인딩: 컨텍스트 개체에 의해 호출되고 컨텍스트 개체에 바인딩됩니다.

예:

function foo() {
    console.log(this.a);
};
var obj = {
    a: 2,
    foo: foo
};
obj.foo();    //2
foo();        //undefined

이 코드에서 foo()는 참조 속성으로 obj 객체에 추가됩니다. obj가 이 참조 속성 함수를 호출하면 참조 속성 컨텍스트가 사용되며 이는 obj에 바인딩됩니다. 물체. . (엄밀히 말하면 이 함수는 obj 객체에 속하지 않고 참조 속성으로만 사용됩니다.) 암시적 바인딩에 속합니다.

아래 foo() 함수의 직접 실행은 obj 객체에 대한 참조가 아니므로 컨텍스트 객체가 전역 객체입니다. 따라서 이는 정의되지 않은 상태로 바인딩됩니다. 기본 바인딩에 속합니다.

객체 참조 체인의 상위 또는 마지막 레이어만 호출 위치에서 역할을 합니다.

참고:

암시적으로 바인딩된 함수는 바인딩된 개체를 잃게 됩니다. 이때 기본 바인딩을 적용하여 엄격 모드인지 여부에 따라 전역 개체 또는 정의되지 않은 개체에 바인딩합니다.
예:

function foo() {
    console.log(this.a);
};
var obj = {
    a: 2;
    foo: foo
}
var bar = obj.foo;
var a = 'biubiubiu';
bar();

运行结果:"biubiubiu"

분석: bar는 obj.foo에 대한 참조인 것으로 보입니다. 실제로 bar는 간단한 함수 호출인 foo 함수를 직접 참조하므로 실제로는 기본 바인딩입니다.

매개변수 전달은 암시적 할당이므로 함수에 전달될 때도 암시적으로 할당됩니다.
예:

function foo() {
    console.log(this.a);
};
var obj = {
    a: 2,
    foo: foo
};
function bar(fn) {
    fn();
};
var a = "biubiubiu";
bar(obj.foo);

运行结果: "biubiubiu"

분석: 실제로 매개변수도 암시적으로 할당되지만 매개변수는 함수에 전달되어 함수에서 실행됩니다. 이때 foo 함수도 직접 참조하므로 기본 바인딩을 사용한 단순 함수 호출이기도 합니다.

함수를 언어 내장 함수에 전달하세요. (기본적으로 위 상황과 유사하게, 자체 선언 함수를 해당 언어의 내장 함수로 변경) 콜백 함수에서 이를 잃어버리는 경우가 흔하며, 콜백 함수를 호출하는 함수에서도 이를 수정할 수 있습니다.

3. 명시적 바인딩

명시적 바인딩: 지정된 개체에 직접 바인딩합니다. Javascript의 대부분의 함수와 사용자가 생성하는 함수는 이 두 가지 명시적 바인딩 방법을 사용할 수 있습니다.

1, .call()
2, .apply()
이 두 가지 바인딩 방법, 첫 번째 매개변수는 여기에 바인딩된 개체입니다. (전달된 매개변수가 원시값(문자열 유형, 불리언 유형, 숫자 유형)인 경우 원시값을 객체 형태(new String, new Boolean, new Number)로 변환합니다. 이를 복싱이라고 합니다.)

예:

function foo() {
    console.log(this.a);
};
var obj = {
    a: 2
};
foo.call(obj);

运行结果: 2

그러나 바인딩을 표시한다고 해서 바인딩 손실 문제가 해결되는 것은 아닙니다. 이때 새로운 친구가 온다 - 하드 바인딩 (바인드).

3. .bind() (하드 바인딩은 일반적인 시나리오이므로 es5는 내장 메서드 Function.prototype.bind를 제공합니다.)
bind()는 새 인코딩 함수를 반환하고 이를 지정된 매개변수를 지정하고 함수를 호출합니다.

예:

function foo(e) {
    console.log(this.a + e);
    return this.a + e;
};
var obj = {
    a: 2
}
var bar = foo.bind(obj); //新编码函数
var b = bar(3); // 2 3
console.log(b); // 5

bind()에는 함수도 있습니다. 이를 하위 함수에 바인딩하는 데 사용된 첫 번째 매개변수를 제외한 다른 매개변수를 전달합니다. ( 부분 적용 , " 유형입니다. 커링").

这里涉及到一个概念:把null或者undefined作为this的绑定对象传入call、apply、bind,这些值在调用的时候会被忽略,实际应用默认绑定规则。
应用场景:
1、使用apply()展开一个数组,并作为参数传递给一个函数。
2、bind()对参数进行柯里化(预先设置一些参数)。

举个栗子:

function foo(a,b) {
    console.log("a:" + a + ",b:" + b);
};
//数组“展开”成参数
foo.apply(null,[2,3]);  //a:2,b:3
//bind()柯里化
var bar = foo.bind(null,2);
bar(3);  //a:2,b:3

解析:传入一个参数作为this绑定对象,如果不传则使用占位符(null),此时会使用默认绑定规则。

上面这个例子可能会产生一定的副作用,如果需要运用这种场景并且更加安全。可以创建一个空对象(可以用任意喜欢的名字来命名)。

var ∅ = Object.create(null);
//上面这个例子就可以改写为:
foo.apply(∅,[2,3]); //a:2,b:3
var bar = foo.bind(∅,2);
bar(3);  //a:2,b:3

注意:硬绑定之后不能使用隐式绑定和显式绑定对this进行修改
在这里介绍一种软绑定的方法softBind()检查this绑定到全局对象或者undefined后,绑定this到指定的默认对象。绑定后效果和硬绑定一样,但是保留隐式绑定或者显式绑定修改this的能力。

四、new绑定

Javascript中的new机制与面向类语言的完全不同。在Javascript中,构造函数只是一些使用new操作符时被调用的函数,不属于一个类,也不会实例化一个类。称为对函数的“构造调用”。

举个栗子:

function foo(a) {
    this.a = a;
}
var bar = new foo(2);
console.log(bar.a); //2

使用new的过程会创建一个全新的对象,this会绑定这个新对象。如果函数没有返回其他对象,则new表达式函数调用会返回该新对象。(这个新对象会连接prototype)

四种绑定规则的优先级为:new>显式>隐式>默认

箭头函数

箭头函数是根据外层作用域(函数或全局)来决定this。(词法作用域取代this机制)
箭头函数this会绑定调用时的对象,且箭头函数的绑定无法修改(new也不行)。

其实可以理解为,箭头函数的this在词法上继承的是它所在的作用域(函数或全局)的this,而它继承的函数作用域的this绑定的是在该函数调用上下文对象,所以箭头函数的this间接的绑定在调用上下文对象。

简述: 箭头函数this(绑定作用域this)-- 作用域this(绑定在调用上下文对象)。

故:箭头函数this == 调用的上下文对象

举个栗子:

function foo() {
    setTimeout(function() {
        //这里的this在词法上继承自foo()
        console.log(this.a);
    },100);
};
var obj = { a: 2 };
foo.call(obj);  //2

其实这个栗子也等价于:

function foo() {
    var that = this;  //lexical capture of this
    setTimeout(function() {
        console.log(self.a)
    },100);
}
...与上面一样

所以,有两种风格:this风格(四种规则)词法作用域风格(that = this和箭头函数)可供使用。使用时尽量避免混用,否则会造成难以维护的后果。

本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注PHP中文网的JavaScript视频教程栏目!

위 내용은 Javascript에서 이것의 사용법에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제