ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript でオブジェクトを作成する 7 つの古典的な方法 (概要)

JavaScript でオブジェクトを作成する 7 つの古典的な方法 (概要)

青灯夜游
青灯夜游転載
2021-01-11 18:25:184185ブラウズ

JavaScript でオブジェクトを作成する 7 つの古典的な方法 (概要)

関連する推奨事項: 「javascript ビデオ チュートリアル

JavaScript でオブジェクトを作成するには、オブジェクト コンストラクターやオブジェクト リテラルを使用するなど、さまざまな方法があります。単一のオブジェクトを作成することもできますが、明らかに、これら 2 つの方法では大量の繰り返しコードが生成されるため、大量生産には適していません。次に、オブジェクトを作成する 7 つの非常に古典的な方法を紹介しますが、それぞれに長所と短所があります。 (内容は主に「JavaScript Advanced Programming」から来ており、他の人が書いた記事も参照しています)

1. ファクトリ パターン

function createPerson(name, job) { 
 var o = new Object();
 o.name = name;
 o.job = job;
 o.sayName = function() { 
  console.log(this.name); 
 } 
 return o 
} 
var person1 = createPerson('Mike', 'student') 
var person2 = createPerson('X', 'engineer')

このファクトリー関数は無制限に呼び出すことができ、毎回 2 つのプロパティと 1 つのメソッドを含むオブジェクトを返します。

ファクトリ パターンは、複数の同様のオブジェクトを作成する問題は解決しますが、オブジェクトの識別の問題は解決しません。つまり、オブジェクトのタイプを知ることができません。

2. コンストラクター モード

function Person(name, job) { 
 this.name = name;
 this.job = job;
 this.sayName = function() { 
  console.log(this.name);
 } 
} 
var person1 = new Person('Mike', 'student') 
var person2 = new Person('X', 'engineer')

作成する表示オブジェクトがありません。このコンストラクターを呼び出すには new を使用してください。new を使用した後は、次の操作:

① 新しいオブジェクトを作成します;

② コンストラクターのスコープを新しいオブジェクトに割り当てます (つまり、これはこの新しいオブジェクトを指します);

③ コンストラクター内のコードを実行します (この新しいオブジェクトにプロパティを追加します);

④ 新しいオブジェクトを返します。

欠点: 各メソッドはインスタンスごとに再作成する必要があります。

同じタスクを完了する 2 つの Function インスタンスを作成する必要はありません。さらに、このオブジェクトを使用すると、コードを実行する前に関数を特定のオブジェクトにバインドする必要がなく、次の形式で定義できます:

function Person( name, age, job ){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = sayName;
}
function sayName(){
    alert( this.name );
}

このようにして、sayName() 関数の定義が完了します。コンストラクターの外に移動することもできます。コンストラクター内で、sayName プロパティをグローバルのsayName 関数に設定します。この場合、sayName には関数へのポインタが含まれるため、person1 オブジェクトと person2 オブジェクトは、グローバル スコープで定義された同じ SayName() 関数を共有できます。

これにより、同じことを行う 2 つの関数の問題は解決されますが、新しい問題が発生します。グローバル スコープで定義された関数は、実際には特定のオブジェクトによってのみ呼び出すことができるため、グローバル スコープになります。ドメインは少し間違った名前です。さらに重要なのは、オブジェクトが多くのメソッドを定義する必要がある場合、多くのグローバル関数を定義する必要があるため、カスタマイズされた参照型にはカプセル化がまったくありません。

これらの問題は、プロトタイプ パターンを使用することで解決できます。

3. プロトタイプ モード

function Person() { 
} 
Person.prototype.name = 'Mike' 
Person.prototype.job = 'student' 
Person.prototype.sayName = function() { 
 console.log(this.name) 
} 
var person1 = new Person()

プロトタイプ オブジェクトに情報を直接追加します。プロトタイプを使用する利点は、すべてのインスタンス オブジェクトがそれに含まれるプロパティとメソッドを共有できることです。コンストラクターでオブジェクト インスタンス情報を定義する代わりに、この情報をプロトタイプ オブジェクトに直接追加できます。

①プロトタイプを理解する

新しい関数が作成されるたびに、特定のルール セットに従って関数のプロトタイプ属性が作成されます。

デフォルトでは、すべてのプロトタイプ プロパティは、プロトタイプ属性が配置されている関数へのポインターを含むコンストラクター (コンストラクター) 属性を自動的に取得します。

コードがオブジェクトのプロパティを読み取るたびに、指定された名前のプロパティをターゲットとして検索が実行されます。検索はオブジェクト インスタンス自体から始まります。指定された名前の属性がインスタンス内で見つかった場合は、その属性の値が返されます。見つからなかった場合は、ポインタが指すプロトタイプ オブジェクトが検索され、指定された名前の属性がプロトタイプ オブジェクト内で見つかります。このプロパティがプロトタイプ オブジェクトで見つかった場合、このプロパティの値が返されます。

プロトタイプに格納されている値にはオブジェクト インスタンスを通じてアクセスできますが、プロトタイプ内の値をオブジェクト インスタンスを通じて上書きすることはできません。

インスタンスにプロパティを追加し、そのプロパティがインスタンス内のプロパティと同じ名前である場合、そのプロパティはインスタンス内に作成され、そのプロパティはプロトタイプ内のそのプロパティをマスクします。

プロパティが null に設定されている場合でも、インスタンス内のプロパティ値のみが null になります。

ただし、delete 演算子を使用するとインスタンスのプロパティを完全に削除できるため、プロトタイプ内のプロパティに再度アクセスできるようになります。

hasOwnProperty() メソッドを使用して、プロパティがインスタンスに存在するかプロトタイプに存在するかを検出します。このメソッドは、指定されたプロパティがオブジェクト インスタンスに存在する場合にのみ true を返します。

②プロトタイプと in 演算子

in 演算子は、プロパティがインスタンスに存在するか、インスタンスに存在するかに関係なく、オブジェクトを通じて特定のプロパティにアクセスできる場合に true を返します。プロトタイプの真ん中。

③より単純なプロトタイプ構文

function Person(){    
}
Person.prototype = {
    name : "Mike",
    age : 29,
    job : "engineer",    
    syaName : function(){
        alert( this.name );
    }
};

上記のコードでは、 person.prototype は、オブジェクト リテラルの形式で作成された新しいオブジェクトと等しく設定されます。最終結果は同じですが、1 つの例外があります。コンストラクター プロパティは Person を指さなくなりました。

四、组合使用构造函数模式和原型模式

组合使用构造函数模式和原型模式是使用最为广泛、认同度最高的一种创建自定义类型的方法。它可以解决上面那些模式的缺点,使用此模式可以让每个实例都会有自己的一份实例属性副本,但同时又共享着对方法的引用,这样的话,即使实例属性修改引用类型的值,也不会影响其他实例的属性值了。还支持向构造函数传递参数,可谓是集两种模式的优点。

function Person(name) { 
 this.name = name; 
 this.friends = ['Jack', 'Merry']; 
} 
Person.prototype.sayName = function() { 
 console.log(this.name); 
} 
var person1 = new Person(); 
var person2 = new Person(); 
person1.friends.push('Van'); 
console.log(person1.friends) //["Jack", "Merry", "Van"] 
console.log(person2.friends) // ["Jack", "Merry"] 
console.log(person1.friends === person2.friends) //false

五、动态原型模式

动态原型模式将所有信息都封装在了构造函数中,初始化的时候。可以通过检测某个应该存在的方法是否有效,来决定是否需要初始化原型。

function Person(name, job) { 
  // 属性 
 this.name = name;
 this.job = job;
 // 方法 
 if(typeof this.sayName !== 'function') { 
  Person.prototype.sayName = function() { 
    console.log(this.name) 
  } 
 } 
} 
var person1 = new Person('Mike', 'Student') 
person1.sayName()

只有在sayName方法不存在的时候,才会将它添加到原型中。这段代码只会初次调用构造函数的时候才会执行。此后原型已经完成初始化,不需要在做什么修改了,这里对原型所做的修改,能够立即在所有实例中得到反映。

其次,if语句检查的可以是初始化之后应该存在的任何属性或方法,所以不必用一大堆的if语句检查每一个属性和方法,只要检查一个就行。

六、寄生构造函数模式

这种模式的基本思想就是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新建的对象

function Person(name, job) { 
  var o = new Object();
 o.name = name;
 o.job = job;
 o.sayName = function() { 
  console.log(this.name) 
 } 
 return o 
} 
var person1 = new Person('Mike', 'student') 
person1.sayName()

这个模式,除了使用new操作符并把使用的包装函数叫做构造函数之外,和工厂模式几乎一样。

构造函数如果不返回对象,默认也会返回一个新的对象,通过在构造函数的末尾添加一个return语句,可以重写调用构造函数时返回的值。

七、稳妥构造函数模式

首先明白稳妥对象指的是没有公共属性,而且其方法也不引用this。稳妥对象最适合在一些安全环境中(这些环境会禁止使用this和new),或防止数据被其他应用程序改动时使用。

稳妥构造函数模式和寄生模式类似,有两点不同:1.是创建对象的实例方法不引用this;2.不使用new操作符调用构造函数

function Person(name, job) { 
 var o = new Object();
 o.name = name;
 o.job = job;
 o.sayName = function() { 
  console.log(name) //注意这里没有了"this";
 } 
 return o 
} 
var person1 = Person('Mike', 'student') 
person1.sayName();

和寄生构造函数模式一样,这样创建出来的对象与构造函数之间没有什么关系,instanceof操作符对他们没有意义

更多编程相关知识,请访问:编程学习!!

以上がJavaScript でオブジェクトを作成する 7 つの古典的な方法 (概要)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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