ホームページ  >  記事  >  ウェブフロントエンド  >  ECMA Javascript についての深い理解 (例付き)

ECMA Javascript についての深い理解 (例付き)

不言
不言転載
2018-11-24 14:05:592224ブラウズ

この記事では、ECMA Javascript について詳しく説明します (例を示します)。必要な方は参考にしていただければ幸いです。

これは実際には、関数が呼び出されたときに発生するバインディングです。それが何を指すかは、関数が呼び出される場所 (つまり、関数がどのように呼び出されるか) によって決まります。

4 つのルール: (知らない JS)

1. デフォルトのバインディング

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

厳密かどうかモードでは、グローバル実行コンテキスト (関数本体の外側) で、これはグローバル オブジェクトを参照します。 (MDN)
厳密モー​​ドでは、実行コンテキストに入ったときにその値が保持されます。これが実行コンテキストによって定義されていない場合は、未定義のままになります。 (MDN)

function foo() {
    "use strict";
    console.log( this.a );
}
var a = 2;
foo(); // TypeError: this is undefined

2. 暗黙的なバインディング/損失

関数がオブジェクト内のメソッドとして呼び出される場合、this は関数を呼び出すオブジェクトであり、バインディングは影響を受けるだけです。最も近いメンバー参照の。 (MDN)

//隐式绑定
function foo() {
    console.log( this.a );
}
var obj2 = {
    a: 42,
    foo: foo
};
var obj1 = {
    a: 2,
    obj2: obj2
};
obj1.obj2.foo(); // 42
//隐式丢失
function foo() {
    console.log( this.a );
}
function doFoo(fn) {
    // fn 其实引用的是 foo
    fn(); // <-- 调用位置!
}
var obj = {
    a: 2,
    foo: foo
};
var a = "oops, global"; // a 是全局对象的属性
doFoo( obj.foo ); // "oops, global"

3. バインディングの表示

this の値をあるコンテキストから別のコンテキストに渡す場合は、call メソッドまたは apply メソッドを使用する必要があります。 (MDN)
f.bind(someObject) を呼び出すと、f と同じ関数本体とスコープを持つ関数が作成されますが、この新しい関数では、この関数がどのような方法であっても、これは永続的にバインドの最初のパラメーターにバインドされます。と呼ばれます。

var obj = {
    count: 0,
    cool: function coolFn() {
    if (this.count < 1) {
        setTimeout( function timer(){
            this.count++; // this 是安全的
                            // 因为 bind(..)
            console.log( "more awesome" );
            }.bind( this ), 100 ); // look, bind()!
        }
    }
};
obj.cool(); // 更酷了。

ハード バインディング

すべてのパラメータを渡し、受け取ったすべての値を返すラッパー関数を作成します。
ハード バインディングを使用すると、関数の柔軟性が大幅に低下します。ハード バインディングを使用した後は、暗黙的バインディングまたは明示的バインディングを使用してこれを変更することはできません。

// 简单的辅助绑定函数
function bind(fn, obj) {
    return function() {
        return fn.apply( obj, arguments );
    };
}

ソフト バインディング

デフォルト バインディングにグローバル オブジェクトと未定義以外の値を指定すると、暗黙的バインディングまたは明示的バインディングの機能を維持しながらハード バインディングと同じ効果を実現できます。これを変更するバインディングの。

Function.prototype.softBind = function(obj) {
    var fn = this;
    var curried = [].slice.call( arguments, 1 );// 捕获所有 curried 参数
    var bound = function() {
        return fn.apply(
            (!this || this === (window || global))?obj : this
            curried.concat.apply( curried, arguments )
        );
    };
    bound.prototype = Object.create( fn.prototype );
    return bound;
};

4. 新しいバインディング

関数がコンストラクターとして使用される場合 (new キーワードを使用)、this は構築される新しいオブジェクトにバインドされます。 (MDN)
new を使用して関数を呼び出すか、コンストラクター呼び出しが発生すると、次の操作が自動的に実行されます (不明な JS)

  1. Create (または構築) 完全に新しいオブジェクト。

  2. この新しいオブジェクトは、[[ プロトタイプ ]] を実行することで接続されます。

  3. この新しいオブジェクトは、関数呼び出しの this にバインドされます。

  4. 関数が他のオブジェクトを返さない場合、新しい式の関数呼び出しは自動的にこの新しいオブジェクトを返します。

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

4 つのルールの優先順位

新しいバインディング>暗黙的なバインディング

  1. 関数は新しい(新しいバインディング)で呼び出されますか?そうである場合、これは新しく作成されたオブジェクトにバインドされます。

     var bar = new foo()
  2. 関数は呼び出し、適用 (明示的バインディング)、またはハード バインディングによって呼び出されますか?そうである場合、これは指定されたオブジェクトにバインドされます。
    さらに: バインディングが null または未定義の場合、実際にはデフォルトのバインディング ルールが適用されます。

     var bar = foo.call(obj2)
  3. 関数はコンテキスト オブジェクトで呼び出されますか (暗黙的にバインドされています)?そうである場合、これはそのコンテキスト オブジェクトにバインドされます。

     var bar = obj1.foo()
  4. どちらでもない場合は、デフォルトのバインディングを使用します。厳密モードの場合は unknown にバインドされ、それ以外の場合はグローバル オブジェクトにバインドされます。

     var bar = foo()

    その中には次のものが含まれます: 間接参照関数にはデフォルトのバインディング ルールが適用されます

    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

Exceptions

##1. アロー関数

アロー関数は、この 4 つの標準ルールを使用しませんが、外部 (関数またはグローバル) スコープに基づいてこれを決定します。

アロー関数では、これはそれを囲む字句コンテキストの this と一致します。 (MDN)
アロー関数は、(this が何にバインドされているかに関係なく) 外部関数呼び出しの this バインディングを継承します。これは実は self = this と同じ仕組みです。
アロー関数のバインディングは変更できません。

2.nodejs

setTimeout(function() { 
    console.log(this) 
    //浏览器中:window 
    //nodejs中:Timeout实例
}, 0)

その他の説明

https://www.zhihu.com/questio...

func(p1, p2) は
func.call(unknown, p1, p2) と同等です

obj.child.method(p1, p2) は

obj.child と同等です.method.call(obj.child, p1, p2)

渡したコンテキストが null または未定義の場合、ウィンドウ オブジェクトがデフォルト コンテキストになります (厳密モードのデフォルト コンテキストは未定義です)

    var number = 50;
    var obj = {
        number: 60,
        getNum: function () {
        var number = 70;
        return this.number;
    }
    }; 

    alert(obj.getNum());
    alert(obj.getNum.call());
    alert(obj.getNum.call({number:20}));

以上がECMA Javascript についての深い理解 (例付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はsegmentfault.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。