ホームページ  >  記事  >  ウェブフロントエンド  >  JavaScript でのオブジェクトの作成とプロトタイプによるオブジェクトの作成を理解する

JavaScript でのオブジェクトの作成とプロトタイプによるオブジェクトの作成を理解する

巴扎黑
巴扎黑オリジナル
2017-08-09 11:21:39888ブラウズ


1. オブジェクトを作成するいくつかの方法

1. 独立宣言モード

var box1 = new Object();	//声明第一个对象并给各属性赋值
box1.name = 'Lee';
box1.age = 100;
box1.run = function () {
	return this.name + this.age + '运行中...';
};
alert(box.run());

var box2 = new Object();	//声明第二个对象并给属性赋值
box2.name = 'Jack';
box2.age = 200;
box2.run = function () {
	return this.name + this.age + '运行中...';
};
alert(box2.run());

この時点では、box2 と box1 は互いに独立しており、混同されません。

しかし、同じ構造のオブジェクトを宣言するたびにコードを追加する必要があり、特に不便なので、次のファクトリーパターンを用意しています。

2. ファクトリモード

function createObject(name, age) { //集中实例化的函数
	var obj = new Object();
	obj.name = name;
	obj.age = age;
	obj.run = function () {
		return this.name + this.age + '运行中...';
	};
	return obj;
}

この方法では、新しいオブジェクトを作成するたびに createObject() メソッドを呼び出すだけで済みます。同時に、オブジェクトを初期化するためのパラメーターも渡すことができます。
しかし、new によって生成されるオブジェクトはすべて Object に従属するため、new によって生成されるオブジェクト間にいくつかの本質的な区別を付けたい場合、現時点では、より単純なコンストラクター モードはありません。

3. コンストラクター パターン

function Box(name, age) {
	this.name = name;
	this.age = age;
	this.run = function () {
		return this.name + this.age + '运行中...';
	};
}
var box1 = new Box('Lee', 100);
var box2 = new Box('Jack', 200);
alert(box1.run());
alert(box1 instanceof Box); //很清晰的识别他从属于Box

コンストラクター パターンは、オブジェクトの再利用とパラメーターの初期化の問題を大幅に解決し、最も一般的に使用される新しいオブジェクト パターンです。
注:

ここでbox1.run != box2.run、それらは参照アドレスを決定するため、2 つのオブジェクトのメソッドは異なる場所に格納されており、2 つの異なるメソッドであることがわかります。
ただし、 box1.run() == box2.run() は、同じ値を返すためです。
オブジェクトを持っている場合、当然、オブジェクトの属性とメソッドの共有が必要になります (たとえば、Java では、サブクラスは親クラスのメンバー変数とメソッドを共有します)。
率直に言うと、コンストラクター パターンによって作成されたオブジェクトは互いに独立しています (上記の box1.run != box2.run など) 2 つのオブジェクト間で特定の属性を共有したい場合は、プロトタイプ プロトタイプを使用する必要があります。 。

2. プロトタイプを通じてオブジェクトを作成する

1. プロトタイプ モード

function Box() {} //声明一个构造函数
Box.prototype.name = 'Lee'; //在原型里添加属性
Box.prototype.age = 100;
Box.prototype.arr = ['aaa','bbb'];
Box.prototype.run = function () { //在原型里添加方法
	return this.name + this.age + '运行中...';
};
var box1 = new Box();
var box2 = new Box();

//修改普通属性,看下会不会影响prototype
alert(box1.name);	//Lee
box1.name = 'Rinima';
alert(box1.name);	//Rinima
alert(box2.name);	//Lee,修改box1的普通属性,相当于直接在box1中添加一个属性,是不会牵扯到原型中的属性的。
					//这一点非常好。但是如果是引用对象(数组)的话,就有问题了。

//修改引用属性,看下会不会影响prototype
alert(box1.arr);	//aaa,bbb
box1.arr.push('ccc');
alert(box1.arr);	//aaa,bbb,ccc
alert(box2.arr);	//aaa,bbb,ccc,修改box1的引用属性,却牵扯到了原型中的属性。
			//这是因为arr只是个引用地址,指向数组真实存储的位置,修改box1中的引用属性就是修改引用所指向的数组,所以原型也被修改了
			//这是我们不希望看到的!

このモードの利点:

1. この時点で、box1.run = = が共有されます。 box2.run
2. 新しいオブジェクトインスタンスの属性が完全に統合されることを保証できます (欠点 2 とは反対です)
このモードの欠点:

1.参照型 オブジェクト内で参照属性を直接変更すると、初期化パラメータの転送が省略され、新しい

のすべての属性が同じになります。
1.1. プロトタイプ リテラル モード

(プロトタイプ モードの別のモード、一般に大きな違いはありません、どちらもプロトタイプ モードに属します)

function Box() {};
Box.prototype = { //使用字面量的方式
	constructor : Box,
	name : 'Lee',
	age : 100,
	run : function () {
		return this.name + this.age + '运行中...';
	}
};

このモードはプロトタイプ モードの長所と短所をすべて継承していますが、また、独自の利点と欠点もあります 利点:

カプセル化をより適切に反映します

欠点:
コンストラクターはそれ自体をポイントしないため、手動で強制的にポイントする必要があります
2. コンストラクター + プロトタイプ モード

function Desk(name, age) { //不共享的使用构造函数
	this.name = name;
	this.age = age;
	this.family = ['aaa', 'bbb', 'ccc'];
};
Desk.prototype = { //共享的使用原型模式
	constructor : Desk,
	run : function () {
		return this.name + this.age + this.family;
	}
};

var desk1 = new Desk('Lee',100);
var desk2 = new Desk('Jack',200);
alert(desk1.family);	//aaa,bbb,ccc
desk1.family.push('ddd');
alert(desk1.family);	//aaa,bbb,ccc,ddd
alert(desk2.family);	//aaa,bbb,ccc

利点:

このモードは、共有属性と非共有属性の問題を完全に解決し、正確に制御できる非常に優れたモードです。

欠点:

ただし、この方法ではプロトタイプとコンストラクターが分離されているため、人々は奇妙に感じ、カプセル化が反映されません。
3. 動的プロトタイプモード

function Box(name ,age) { //将所有信息封装到函数体内
	this.name = name;		//不共享的属性
	this.age = age;
	
	if (typeof this.arr != 'object') {		//共享的属性
		alert('在第一次调用的时候...arr');
		Box.prototype.arr = ['aaa','bbb'];
	}
	if (typeof this.run != 'function') {
		alert('在第一次调用的时候...run');
		Box.prototype.run = function () {
			return this.name + this.age + '运行中...';
		};
	}
}
var box1 = new Box();
var box2 = new Box();
alert( box1.arr );		//aaa,bbb
box1.arr.push('ccc');
alert( box1.arr );		//aaa,bbb,ccc
alert( box2.arr );		//aaa,bbb

利点: このモードは、前のモード (構築 + プロトタイプ) のすべての利点を継承し、カプセル化の問題も完全に解決します

注: このモードでプロトタイプを作成する場合、リテラルは使用できません。インスタンスと新しいプロトタイプの間の接続が切断されます。 ? ? ?



基本的に現時点では、上記の 2 つのモードでほとんどの問題を処理でき、より優れたモードです。
ただし、次の 2 つの代替モードの使用を必要とする、比較的特殊なニーズがまだいくつかあります。


4. 寄生コンストラクターモード (ファクトリーモード + コンストラクターモード)

function Box(name, age) {
	var obj = new Object();
	obj.name = name;
	obj.age = age;
	obj.run = function () {
		return this.name + this.age + '运行中...';
	};
	return obj;
}

5. 安全なコンストラクターモード

function Box(name , age) {
	var obj = new Object();
	obj.run = function () {
		return name + age + '运行中...'; //直接打印参数即可
	};
	return obj;
}

安全なコンストラクターモードは、コンストラクター、外部インスタンス化での使用が許可されていない場合です。 new の使用が許可されていない場合にのみ必要です。

なぜそのような奇妙な要求があるのか​​わかりません。しかし、非常に多くのオブジェクト作成パターンは、確かに Java よりもはるかに魅力的です。



以上がJavaScript でのオブジェクトの作成とプロトタイプによるオブジェクトの作成を理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。