ホームページ > ウェブフロントエンド > jsチュートリアル > ECMA Javascript についての深い理解 (例付き)

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

不言
リリース: 2018-11-24 14:05:59
転載
2262 人が閲覧しました

この記事では、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 までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート