JavaScript>引き継ぎとコピー
7016 ワード
JavaScript継承とコピー
Date:7 th of Aug,2015
Author:HaoyCn
本論文では、JavaScriptでの継承関係の実現と、オブジェクトのコピー方法について議論します.以下、それぞれ4つの継承方法を検討します.相続方法を話してから、対象のコピーについて話します.
先に説明する必要があるのは、後文で継承したいコンストラクタの関数は:
本方法の特性は、再利用可能な部分をプロトタイプチェーンに移行することができ、再利用できない場合は対象の自身の属性として設定されます. ルックアップ は .
原型のみから法を継承する
「プロトタイプチェーン継承法」に比べ、本方法の利点は、運転時の効率が向上し、新規オブジェクトが作成されていないことです. ルックアップ 一歩減った.しかしながら、価格は、
致命的な欠点の一つは、サブ構造のオブジェクトを修正できない
テストします
「原型継承法のみ」の問題が発覚しました.
「一時的コンストラクタ継承法」は、次のような仲介関数を使用します. ルックアップ ルックアップ .
この方法は最初の「原型継承法のみ」と比べて、どのような進歩がありますか?
まず「原型継承法のみ」の操作を見てください.
コンストラクタ借用法
以上の継承法に共通する欠点の一つは、
コンストラクター借用法が生まれました.
原型属性コピー法
プロトタイプ機構を利用した.高級ブラウザでは、
問題を目の前に置いて、どうやって深くコピーしますか?
私たちのコピー対象は「原型属性コピー法」のほかに、従来の遍及でも可能です.浅いコピーのように巡回:
以上です.純粋でない対象に対しての深いコピーの方法については、例えば
Date:7 th of Aug,2015
Author:HaoyCn
本論文では、JavaScriptでの継承関係の実現と、オブジェクトのコピー方法について議論します.以下、それぞれ4つの継承方法を検討します.相続方法を話してから、対象のコピーについて話します.
先に説明する必要があるのは、後文で継承したいコンストラクタの関数は:
var Animal = function(name){
this.name = name;
};
Animal.prototype.jump = function(){
console.log('jumped');
};
プロトタイプ相続法本方法の特性は、再利用可能な部分をプロトタイプチェーンに移行することができ、再利用できない場合は対象の自身の属性として設定されます.
var Human = function(name){
this.name = name;
};
//
// Human.prototype.constructor = Animal;
//
Human.prototype = new Animal;
//
// `Human` `Animal` `Human`
Human.prototype.constructor = Human;
var man = new Human('HaoyCn');
man.jump();
次に、オブジェクトman
は、Animal.prototype.jump
方法を使用することができ、検索プロセスは:man
自体にはjump
方法がないman.constructor.prototype
、すなわちHuman.prototype
は、Human.prototype
自体もjump
方法がなく、Animal
によって構成されたオブジェクトであるため、Animal.prototype
を検索し、jump
の方法が見つかった.実行する原型のみから法を継承する
「プロトタイプチェーン継承法」に比べ、本方法の利点は、運転時の効率が向上し、新規オブジェクトが作成されていないことです.
var Human = function(name){
this.name = name;
};
Human.prototype = Animal.prototype;
var man = new Human('HaoyCn');
man.jump();
この時の検索過程は以下の通りです.man
自体にはjump
方法がないman.constructor.prototype
、すなわちHuman.prototype
、Human.prototype
はAnimal.prototype
の参照であり、jump
の方法が発見され、実行されるHuman.prototype
の修正は、前者が後者への参照であるため、Animal.prototype
に影響を与える.致命的な欠点の一つは、サブ構造のオブジェクトを修正できない
constructor
です.テストします
man.constructor === Animal;//true
new
のプロセスを振り返ってみましょう.var newProcess = function(){
var ret;
//
var obj = {};
//
var Constructor = Array.prototype.shift.call(arguments);
//
obj.__proto__ = Constructor.prototype;
//
ret = Constructor.apply(obj,arguments);
//
return 'object' === typeof ret ? ret : obj;
};
これにより、「原型継承法のみから」man
はどのように作成されたかを振り返ってみます.// var man = newProcess(Human,'HaoyCn');
//
var ret;
var man = {};
// var Constructor = Array.prototype.shift.call(arguments);
//
//var Constructor = Human;
man.__proto__ = Human.prototype;
// ret = Human.apply(obj,arguments);
// `Human`
man.name = 'HaoyCn';
// `Human` undefined, ret = undefined;
// `newProcess` `man`
したがって、理解は難しくないです.man.constructor ===
man.__proto__.constructor ===
Human.prototype.constructor ===
Animal.prototype.constructor ===
Animal
仮コンストラクタ継承法「原型継承法のみ」の問題が発覚しました.
Animal.prototype
はHuman.prototype
に対する修正によって変更されます.変更されるとAnimal
によって構成されたオブジェクトも変更されます.例を挙げます.var monkey = new Animal('monkey');
var woman = new Human('woman');
monkey.jump();// jumped
woman.jump();// jumped
// `Animal.prototype`
Human.prototype.jump = function(){
console.log('I refuse');
};
//
monkey.jump();// I refuse
woman.jump();// I refuse
じゃ、私たちはどうやってこの問題を回避しますか?「一時的コンストラクタ継承法」は、次のような仲介関数を使用します.
var F = function(){};
F.prototype = Animal.prototype;
var Human = function(name){
this.name = name;
};
Human.prototype = new F;
Human.prototype.constructor = Human;
Human.prototype.sing = function(){
console.log('Mayday');
};
var man = new Human('HaoyCn');
man.jump();
man.sing();
Human.prototype
に対する任意の変更は、仲介コンストラクタによって作成されたオブジェクトの属性に対する修正となる.jump
検索プロセスは、man
自体にはjump
方法がないman.constructor.prototype
、すなわちHuman.prototype
は、Human.prototype
自体もjump
方法がなく、F
によって構成されたオブジェクトであるため、F.prototype
、すなわちAnimal.prototype
は、jump
の方法が発見され、実行されるこの方法は最初の「原型継承法のみ」と比べて、どのような進歩がありますか?
まず「原型継承法のみ」の操作を見てください.
Human.prototype = new Animal;
// :
// Human.prototype.name = undefined;// `Animal`
つまり、Human.prototype
は不必要な属性が多くなり、仲介器はこの不必要な属性を回避する.コンストラクタ借用法
以上の継承法に共通する欠点の一つは、
Human
ビルダー構造のオブジェクトはAnimal.prototype
を共有することができるが、name
属性については、Human
ビルダーは自分で構造name
属性を書き直すしかないということです.なぜ初期化属性の方法を共用しないのですか?コンストラクター借用法が生まれました.
name
属性の作成をAnimal
に渡し、Human
属性を追加します.私たちは「臨時コンストラクター法」に基づいてさらに改善しています.var F = function(){};
F.prototype = Animal.prototype;
var Human = function(){
Animal.apply(this,arguments);
this.country = arguments[1];
}
Human.prototype = new F;
Human.prototype.constructor = Human;
var man = new Human('HaoyCn','China');
console.log(man.country);// China
これで、私たちはリラックスして怠けを完成しました.これはPHPにおける構造関数のカバー方法を思い付きました.// PHP
class Human{
public $name;
public $country;
function __construct($name,$country){
parent::__construct($name);
$this->country = $country;
}
}
相続に関する話はこれで終わります.コピーについて話します.原型属性コピー法
プロトタイプ機構を利用した.高級ブラウザでは、
country
方法でオブジェクトのコピーを完了します.Object.create = Object.create || function(obj){
var F = function(){};
F.prototype = obj;
return new F;
}
これは薄いコピーです.私たちがコピーされたオブジェクトを修正すれば、新しいオブジェクトにも影響します.以下の例を示しますvar man = {
name: 'HaoyCn',
jump: function(){
console.log('jumped');
}
};
var monkey = Object.create(man);
monkey.jump();// jumped
man.jump = function(){
console.log('I refuse');
};
monkey.jump();// I refuse
浅いコピーと深いコピー問題を目の前に置いて、どうやって深くコピーしますか?
私たちのコピー対象は「原型属性コピー法」のほかに、従来の遍及でも可能です.浅いコピーのように巡回:
var man = {
name: 'HaoyCn',
jump: function(){
console.log('jumped');
}
};
var monkey = {};
for(var i in man){
monkey[i] = man[i];
}
monkey.jump();// jumped
深くコピーするということは、属性がまだ対象であれば、コピーするということです.function deepCopy(origin,copy){
copy = copy || {};
for(var i in origin){
if('object' === typeof origin[i]){
// ,
copy[i] = ('Array' === origin[i].constructor) ? [] : {};
deepCopy(origin[i],copy[i]);
}else{
copy[i] = origin[i];
}
}
}
以上は深いコピーの一つの要約原理コードです.より複雑な検査プロセスは、Object.create
を参照することができる.しかし、このようなコピー(jQuery.extend
の深度コピーを含む)は、純粋なオブジェクトに対する深いコピーしかできません.関数、RegExp、Dateなどは、深くコピーできません.以上です.純粋でない対象に対しての深いコピーの方法については、例えば
jQuery.extend
を呼び出してから対象を構築する方式ですが、十分ではありません.この点で心得があれば、教えてください.