フロントエンドを学ぶときに、多くの友人がオブジェクト作成で困難に遭遇するでしょう。いくつかの方法を教えてください。根気よく学んでください。
1. オブジェクトの作成方法
1. ファクトリパターン
関数内でオブジェクトを作成し、オブジェクトに属性を追加し、関数内でオブジェクトを返します。オブジェクトのインスタンスを作成するには、関数の外でこの関数を呼び出します。
function createPerson(name,age,job){ var o=new Object();//在函数内部创建一个对象 o.name=name; o.age=age; o.job=job; o.sayName=function(){ alert(this.name); }; return o;//在函数内部返回这个对象 } var person1=createPerson("xiaowang","22","workers");//在函数外部创建对象的实例,不用new var person1=createPerson("xiaoliu","22","workers");
問題: オブジェクトの識別問題が解決されていない (オブジェクトの型がわからない)
2. コンストラクター パターン (特定の型のオブジェクトを作成するために使用できます)
function Person(name,age,job){//注意构造函数开头的字母应该大写 //构造函数中使用this this.name=name; this.age=age; this.job=job; this.sayName=function(){ alert(this.name); } } var person1=new Person("xiao",22,"tech");//使用new创建实例 var person2=new Person("li",32,"sin");
ファクトリ パターンとの違い:
(1) 作成したオブジェクトの表示はありません
(2) thisが指すオブジェクトに直接プロパティやメソッドを代入します
(3) return文はありません
どちらのインスタンスもコンストラクタ属性を持ち、人を指しています。
コンストラクターはそのインスタンスがどのようなタイプのオブジェクトであるかを識別でき、instanceof 演算子を使用する方がより信頼性が高くなります。
Q: コンストラクターと通常の関数の違いは何ですか?
答え: コンストラクターは new 演算子を使用して呼び出され、通常の関数は new なしで呼び出されます。
コンストラクターに関する問題: 各メソッドは各インスタンスで再作成する必要があります。
3. プロトタイプパターン
オブジェクトインスタンスが共有するプロパティとメソッドをコンストラクターではなくプロトタイプオブジェクトに置きます。
function Person(){ };//构造函数什么也不设置 Person.prototype.name="xiao";//全部都放在原型对象上 Person.prototype.age=22; Person.prototype.job="stu"' Person.prototype.sayName=function(){ alert(this.name); } var person1=new Person(); var person2=new Person(); console.log(person1.sayName==person2.sayName);//true
プロトタイプ パターンの問題: アプリケーション タイプの値を含む属性の場合、プロトタイプ パターンの共有により、1 つのインスタンスの参照タイプの値が変更されると、他のインスタンスの属性値も変更されてしまいます。
function Person={} Person.prototype={ constructor:Person, name:"Nick", age:29, friends:['a','b'];//引用类型的值 sayName:function(){ alert(this.name); } } var person1=new Person(); var person2=new Person(); //想要改变person1实例的friends属性 person1.friends.push("c); alert(person1.friends);//["a","b","c"] alert(person2.friends);//["a","b","c"]; alert(person1.friends==person2.friends);//true;
4. 組み合わせパターン(コンストラクターとプロトタイプ)
コンストラクターはインスタンスのプロパティを定義し、プロトタイプはメソッドと共有プロパティを定義します。
function Person(name,age,job){ this.name=name; this.age=age; this.job=job; } Person.prototype={ constructor:Person, sayname:function(){ alert(this.name) } }
1. 理解
各コンストラクター パーソン は、そのプロトタイプ オブジェクトを指すプロトタイプ属性を持ちます。つまり、プロトタイプ オブジェクトは Person.prototype であり、各プロトタイプ オブジェクトには、使用されるコンストラクター メソッドがあります。コンストラクター Person をポイントバックします。さらに、コンストラクターを呼び出して作成されたインスタンス person1 には [[Prototype]] 属性 (_proto_) があり、これもコンストラクターのプロトタイプ オブジェクトを指します。 インスタンスとコンストラクターのプロトタイプ オブジェクトの間で接続が発生することに注意してください !そして、インスタンスはコンストラクターとは何の関係もありません。
isPrototypeOf() メソッド: プロトタイプ オブジェクトとインスタンスにプロトタイプの接続関係があるかどうかを検出します。
Person.prototype.isPrototypeOf(person1);//true
Object.getPrototypeOf() メソッド: このメソッドは、プロトタイプ オブジェクトを返す [[prototype]] の値を返します。インスタンスの。
Object.getPrototypeOf(person1);// Person.prototype
注: 必ず最初にコンストラクターのプロトタイプ オブジェクトを設定してから、新しいインスタンスを作成してください。 (プロトタイプのダイナミクス)
例:
function Person(){ } var friend=new Person(); Person.prototype={ constructor:Person, name:'Nick', age:29, job:'student', sayName:function () { alert(this.name); } }; friend.sayName();//error
この場合、人のプロトタイプが書き換えられます: p.157
2. 属性アクセス
Q: プロトタイプ ([[プロトタイプ]]) 参照とは効果?
回答: オブジェクトのプロパティを参照すると、基礎となる [[Get]] 操作がトリガーされます。デフォルトの [[Get]] 操作の場合、最初のステップはオブジェクト自体にこの属性があるかどうかを確認することです。持っていない場合は、[[Prototype]] チェーンが役立ちます。オブジェクト自体に必要な属性がない場合は、プロトタイプ チェーン全体に沿って検索が続行され、見つかった場合はその属性の値が返されます。
for...in... オブジェクトを走査する原理は、検索 [[Prototype]] チェーンと似ています。 in 演算子を使用してオブジェクトにプロパティが存在するかどうかをチェックする場合、(プロパティが列挙されているかどうかに関係なく) オブジェクトのプロトタイプ チェーン全体もチェックされます。
[[Prototype]] プロトタイプ チェーンの先頭は Object.prototype オブジェクトに設定されます。
3. 属性の設定とシールド
myObject.foo="bar";//设置属性foo
ステップ 1: myObject オブジェクトに属性 foo がある場合、foo を直接「bar」に変更します。
ステップ 2: foo 属性が myObject とプロトタイプ チェーンの両方に存在する場合、foo 属性on myObject は、プロトタイプ チェーン上のすべての foo 属性をブロックします。
ステップ 3: myObject オブジェクトに属性 foo がない場合、それが検索され、myObject のプロトタイプ チェーンに存在します。 foo 属性はチェーンの上位層に存在し、読み取り専用としてマークされていない (書き込み可能: false) ので、シールド属性である foo 属性を myObject に直接追加します。
var myObject={ }; myObject.prototype={ foo:"c" }; myObject.foo="b"; console.log(myObject.foo);//b
3.2 foo 属性の場合が読み取り専用 Read としてマークされている場合、既存のプロパティを変更したり、myObject でシールドされたプロパティを作成したりすることはできません。厳密モードの場合、エラーがスローされます。
var myObject={ }; myObject.prototype={ foo:"c" }; Object.defineProperty(myObject,"foo",{ writable:false }) myObject.foo="b"; console.log(myObject.foo);//undefined
3.3 foo が [[Prototype]] に存在し、セッターである場合、このセッターは必ず呼び出されます。 foo は myObject に追加されず、このプロパティのセッターも再定義されません。
var myObject={ }; myObject.prototype={ //foo是一个setter set foo(val){ alert(this.val); } } myObject.foo="f"; console.log(myObject.foo)//f foo还是原来的setter函数,没有被修改
如果在3.2和3.3这两种情况下,则不能使用=操作符在赋值,而是使用Object.defineProperty(...)方法来添加,
step4:如果myObject对象和原型链上都没有foo属性的时候,直接添加到myObject上。
var myObject={ }; myObject.prototype={ foo:"c" }; myObject.foo="b"; console.log(myObject.foo);//b
4.属性的修改
对象实例可以修改对象原型的属性值吗?
答:分两种情况:一:当原型里的属性是值类型的话,不会被修改;
function ClassA(){}; ClassA.prototype.num=4;//num为值类型 const a=new ClassA(); a.num=3; const b=new ClassA(); console.log(b.num);
二:当原型里的属性是引用类型的话,则会被修改。
function ClassA(){}; ClassA.prototype.obj={ num:4//num在object中,是引用类型 }; const a=new ClassA(); a.obj.num=3; const b=new ClassA(); console.log(b.obj.num);
相关推荐:
JavaScript 基于原型的对象(创建、调用)_js面向对象
以上がオブジェクトのメソッドとプロトタイプオブジェクトを作成する方法を学習します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。