ホームページ >ウェブフロントエンド >jsチュートリアル >これ、コンストラクター、js cliché_javascript のプロトタイプのスキルを総合的に分析

これ、コンストラクター、js cliché_javascript のプロトタイプのスキルを総合的に分析

WBOY
WBOYオリジナル
2016-05-16 15:06:291496ブラウズ

はしがき

JavaScript の This、コンストラクター、プロトタイプはすべてよくある問題であり、その意味を深く理解することが重要です。ここで、もう一度見直して、過去を振り返り、新しいことを学びましょう!

これ

これは現在のオブジェクトを表します。これがグローバル スコープで使用される場合は、現在のページ オブジェクト ウィンドウを参照します。これが関数で使用される場合、これが参照する内容は、この関数が呼び出されるオブジェクトに基づきます。実行時。 また、2 つのグローバル メソッド apply と call を使用して、関数内の this の特定のポインタを変更することもできます。

まず、これをグローバル スコープで使用する例を見てみましょう:

console.log(this === window); // true
console.log(window.alert === this.alert); // true
console.log(this.parseInt("021", 10)); // 10

関数内のこれは、次のように、関数の定義時ではなく実行時に決定されます。

// 定义一个全局函数
    function foo() {
      console.log(this.fruit);
    }
    // 定义一个全局变量,等价于window.fruit = "apple";
    var fruit = "apple";
    // 此时函数foo中this指向window对象
    // 这种调用方式和window.foo();是完全等价的
    foo(); // "apple"

    // 自定义一个对象,并将此对象的属性foo指向全局函数foo
    var pack = {
      fruit: "orange",
      foo: foo
    };
    // 此时函数foo中this指向window.pack对象
    pack.foo(); // "orange"
グローバル関数 apply と call を使用すると、次のように関数内で this のポインタを変更できます。

// 定义一个全局函数
    function foo() {
      console.log(this.fruit);
    }

    // 定义一个全局变量
    var fruit = "apple";
    // 自定义一个对象
    var pack = {
      fruit: "orange"
    };

    // 等价于window.foo();
    foo.apply(window); // "apple"
    // 此时foo中的this === pack
    foo.apply(pack);  // "orange"
注: apply 関数と call 関数は同じ関数です。唯一の違いは、2 つの関数のパラメーター定義が異なることです。

JavaScript では関数もオブジェクトであるため、次の興味深い例がわかります:

// 定义一个全局函数
    function foo() {
      if (this === window) {
        console.log("this is window.");
      }
    }

    // 函数foo也是对象,所以可以定义foo的属性boo为一个函数
    foo.boo = function() {
      if (this === foo) {
        console.log("this is foo.");
      } else if (this === window) {
        console.log("this is window.");
      }
    };
    // 等价于window.foo();
    foo(); // this is window.

    // 可以看到函数中this的指向调用函数的对象
    foo.boo(); // this is foo.

    // 使用apply改变函数中this的指向
    foo.boo.apply(window); // this is window.

プロトタイプ

プロトタイプは本質的に JavaScript オブジェクトです。

そして、各関数にはデフォルトのプロトタイプ属性があります。 この関数がカスタム オブジェクトの作成のコンテキストで使用される場合、この関数をコンストラクターと呼びます。 たとえば、次の単純なシーン:


// 构造函数
    function Person(name) {
      this.name = name;
    }
    // 定义Person的原型,原型中的属性可以被自定义对象引用
    Person.prototype = {
      getName: function() {
        return this.name;
      }
    }
    var hao= new Person("haorooms");
    console.log(hao.getName());  // "haorooms"
例として、JavaScript のデータ型 (文字列、数値、配列、オブジェクト、日付など) を考えてみましょう。

これらの型は、次のような JavaScript 内のコンストラクターとして実装されていると考える理由があります。

// 定义数组的构造函数,作为JavaScript的一种预定义类型
    function Array() {
      // ...
    }

    // 初始化数组的实例
    var arr1 = new Array(1, 56, 34, 12);
    // 但是,我们更倾向于如下的语法定义:
    var arr2 = [1, 56, 34, 12];
同時に、配列を操作する多くのメソッド (concat、join、push など) もプロトタイプ属性で定義する必要があります。 実際、JavaScript のすべての組み込みデータ型には読み取り専用のプロトタイプ属性があります (これは理解できます。これらの型のプロトタイプ属性を変更すると、事前定義されたメソッドは消えます)。しかし、それに独自の拡張メソッドを追加できます。

// 向JavaScript固有类型Array扩展一个获取最小值的方法
    Array.prototype.min = function() {
      var min = this[0];
      for (var i = 1; i < this.length; i++) {
        if (this[i] < min) {
          min = this[i];
        }
      }
      return min;
    };

    // 在任意Array的实例上调用min方法
    console.log([1, 56, 34, 12].min()); // 1
注: ここには罠があります。配列のプロトタイプに拡張メソッドを追加した後、for-in を使用して配列をループすると、この拡張メソッドもループアウトされます。 次のコードはこれを示しています (min メソッドが Array プロトタイプに拡張されていると仮定しています)。

var arr = [1, 56, 34, 12];
    var total = 0;
    for (var i in arr) {
      total += parseInt(arr[i], 10);
    }
    console.log(total);  // NaN
解決策も非常に簡単です:

var arr = [1, 56, 34, 12];
    var total = 0;
    for (var i in arr) {
      if (arr.hasOwnProperty(i)) {
        total += parseInt(arr[i], 10);
      }
    }
    console.log(total);  // 103

コンストラクター
constructor は常に、現在のオブジェクトを作成したコンストラクターを指します。たとえば、次の例:


// 等价于 var foo = new Array(1, 56, 34, 12);
    var arr = [1, 56, 34, 12];
    console.log(arr.constructor === Array); // true
    // 等价于 var foo = new Function();
    var Foo = function() { };
    console.log(Foo.constructor === Function); // true
    // 由构造函数实例化一个obj对象
    var obj = new Foo();
    console.log(obj.constructor === Foo); // true

    // 将上面两段代码合起来,就得到下面的结论
    console.log(obj.constructor.constructor === Function); // true
しかし、コンストラクターがプロトタイプに遭遇すると、興味深いことが起こります。 各関数にはデフォルトの属性プロトタイプがあり、このプロトタイプのコンストラクターはデフォルトでこの関数を指すことがわかっています。次の例に示すように:

function Person(name) {
      this.name = name;
    };
    Person.prototype.getName = function() {
      return this.name;
    };
    var p = new Person("haorooms");

    console.log(p.constructor === Person); // true
    console.log(Person.prototype.constructor === Person); // true
    // 将上两行代码合并就得到如下结果
    console.log(p.constructor.prototype.constructor === Person); // true
関数のプロトタイプを再定義したとき (注: 上記の例との違い、これは変更ではなくオーバーライドです)、次の例に示すように、コンストラクターの動作が少し奇妙でした。 >

なぜですか? Person.prototype をオーバーライドする場合、次のコード操作を実行するのと同じであることがわかります:
function Person(name) {
      this.name = name;
    };
    Person.prototype = {
      getName: function() {
        return this.name;
      }
    };
    var p = new Person("haorooms");
    console.log(p.constructor === Person); // false
    console.log(Person.prototype.constructor === Person); // false
    console.log(p.constructor.prototype.constructor === Person); // false

コンストラクターは常に、それ自体を作成するコンストラクターを指すため、この時点では Person.prototype.constructor === Object、つまり
Person.prototype = new Object({
      getName: function() {
        return this.name;
      }
    });

この問題を解決するにはどうすればよいですか?メソッドも非常に簡単で、 Person.prototype.constructor をオーバーライドするだけです:
function Person(name) {
      this.name = name;
    };
    Person.prototype = {
      getName: function() {
        return this.name;
      }
    };
    var p = new Person("haorooms");
    console.log(p.constructor === Object); // true
    console.log(Person.prototype.constructor === Object); // true
    console.log(p.constructor.prototype.constructor === Object); // true

は次のように書くこともできます:
function Person(name) {
      this.name = name;
    };
    Person.prototype = {
      getName: function() {
        return this.name;
      }
    };
    Person.prototype.constructor = Person;
    var p = new Person("haorooms");
    console.log(p.constructor === Person); // true
    console.log(Person.prototype.constructor === Person); // true
    console.log(p.constructor.prototype.constructor === Person); // true

js クリシェの this、コンストラクター、プロトタイプに関する上記の包括的な分析は、すべて編集者が共有した内容です。参考にしていただければ幸いです。また、皆様にも Script Home をサポートしていただければ幸いです。
function Person(name) {
      this.name = name;
    };
    Person.prototype = {
     constructor:Person,//指定constructor
      getName: function() {
        return this.name;
      }
    };
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。