Personの新しいインスタンスを作成するには、new演算子を使用する必要があります。この方法でコンストラクターを呼び出すと、実際には次の4つの手順が実行されます。
- 新しいオブジェクトを作成します。
- コンストラクターのスコープを新しいオブジェクトに割り当てます(したがって、これはこの新しいオブジェクトを指します)。
- コンストラクターでコードを実行します(この新しいオブジェクトに属性を追加します)。
- 新しいオブジェクトを返します。
1.新しいオペレーター
上記の基本概念を導入し、新しい演算子を追加した後、従来のオブジェクト指向クラスと新しいメソッドを完成させてオブジェクトを作成できます。JavaScriptでは、このタイプのメソッドをPseudoclassicalと呼びます。
上記の例に基づいて、次のコードを実行します
var obj = new Base();
このコードの結果は何ですか?Javascriptエンジンに表示されるオブジェクトモデルは次のとおり
です。new演算子は何をしますか?実際には非常に単純で、3つのことを行います。
var obj = {
};
obj.proto = Base.prototype;
Base.call(obj);
第一行,我们创建了一个空对象obj;
第二行,我们将这个空对象的 __proto__ 成员指向了 Base 函数对象 prototype 成员对象;
第三行,我们将 Base 函数对象的 this 指针替换成obj,然后再调用 Base 函数,于是我们就给 obj 对象赋值了一个 id 成员变量,
这个成员变量的值是 ”base” ,关于 call 函数的用法。
Base.prototypeオブジェクトにいくつかの関数を追加すると、どのような効果がありますか?
Base.prototype.toString = function() {
return this.id;
}
次に、newを使用して新しいオブジェクトを作成すると、protoの特性に応じて、toStringメソッドに新しいオブジェクトメソッドとしてアクセスすることもできます。
つまり
、サブオブジェクトの構築では、「クラス」のメンバー変数(例:例ではid)を設定し、サブオブジェクトのプロトタイプの構築では、パブリックを設定します。 'クラス'のメソッド。そのため、関数オブジェクトとJavascriptの一意の__プロトタイプ__およびプロトタイプメンバーと新しい演算子を使用して、クラスとクラスのインスタンス化の効果がシミュレートされます。
2.新しい操作中に何が起こったのか
ほとんどのフロントエンド開発者にとって、新しいコンストラクターまたはクラスの対応するインスタンスを取得することは非常に一般的な操作です。
次の例では、インスタンスを作成する簡単なプロセスが、それぞれコンストラクターとクラスクラスを介して実現されています。
// ES5构造函数
let Dog = function (name, age) {
this.name = name;
this.age = age;
};
Dog.prototype.sayName = function () {
console.log(this.name);
};
const myDog = new Dog('汪汪', 2);
myDog.sayName() // '汪汪'
// ES6 class类
class Cat {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayName() {
console.log(this.name);
}
};
const myCat = new Cat('QIU', 3);
myCat.sayName(); // QIU
しかし、新しいものはブラックボックスのようなものであってはなりません。結果を知ることに加えて、プロセスも理解する必要があります。
より直感的な意味で、コンストラクターを新しく作成すると、取得されたインスタンスはコンストラクターの構築プロパティ(this.name these)とプロトタイプのプロパティを継承します。
「JavaScriptパターン」という本では、新しいプロセスはより簡単です。コンストラクターを新しくする場合、3つの主要なステップがあります。
- 空のオブジェクトを作成し、その参照をこれに割り当て、関数のプロトタイプを継承します。
- これを介して、このオブジェクトにプロパティとメソッドを追加します。
- 最後に、これが指す新しいオブジェクトを返します。これはインスタンスです(他のオブジェクトが手動で返されない場合)。
上記の例を書き直してください。おそらく次のようになります。
// ES5构造函数
let Dog = function (name, age) {
// 1.创建一个新对象,赋予this,这一步是隐性的,
// let this = {};
// 2.给this指向的对象赋予构造属性
this.name = name;
this.age = age;
// 3.如果没有手动返回对象,则默认返回this指向的这个对象,也是隐性的
// return this;
};
const myDog = new Dog();
これを理解するのは難しいことではありません。作業で次のコードのような操作を確認し、これを新しい変数(そのような)に割り当て、最後にこの変数を返す必要があります。
// ES5构造函数
let Dog = function (name, age) {
let that = this;
that.name = name;
that.age = age;
return that;
};
const myDog = new Dog('汪汪', 2);
なぜこれを書くのですか?
これの作成と返却は暗黙的であると先に述べましたが、建設プロセスをより見やすくし、作業中の保守を容易にするために、これの代わりにそれを使用して手動で返す上記の方法
も検証されています。2つのステップセックスの存在はありません。
しかし、上記の説明は私には完璧ではありません。コンストラクターのプロパティがインスタンスに挿入される方法についてのみ説明し、プロトタイプのプロパティがインスタンスによってどのように継承されるかについては説明していません。
Winter Great Godの再学習のフロントエンドのコラムで、私は自分の心に、そしてまた原則に沿った説明を見ました。
- コンストラクターのprototypeプロパティをプロトタイプとして使用して、新しいオブジェクトを作成します。
- これ(つまり、前の文の新しいオブジェクト)と呼び出しパラメーターをコンストラクターに渡して実行します。
- コンストラクターが手動でオブジェクトを返さない場合は、最初のステップで作成されたオブジェクトを返します。
ここで何を言おうと、おそらく新しいプロセスを知っているはずです。オブジェクトが作成され、このオブジェクトはコンストラクターのプロトタイプとプロトタイプのプロパティを継承し、最後にインスタンスとしてそのようなプロセスに返されます。 。原理を知って、簡単な新しいメソッドを手動で実装しましょう。
3.単純な新しいメソッドを実装します
// 构造器函数
let Dog = function (name, age) {
this.name = name;
this.age = age;
};
Dog.prototype.sayName = function () {
console.log(this.name);
};
// 定义的new方法
let newMethod = function (Dog, ...rest) {
// 1. 以构造器的 prototype 属性为原型,创建新对象;
let myDog = Object.create(Dog.prototype);
// 2. 将this和调用参数传给构造器执行
Dog.apply(myDog, rest);
// 3. 返回第一步的对象
return myDog;
};
// 创建实例,将构造函数 Dog 与形参作为参数传入
const myDog = newMethod(Dog, '汪汪', 2);
myDog.sayName() // '汪汪';
// 最后检验,与使用new的效果相同
console.log( myDog instanceof Dog ) // true
console.log( myDog.hasOwnProperty('name') ); // true
console.log( myDog.hasOwnProperty('age') ); // true
console.log( myDog.hasOwnProperty('sayName') );// false