function Cat (name, color) { return { name: name, color: color } } var cat1 = Cat("大毛", "黃色");//{name: "大毛", color: "黃色"} var cat2 = Cat("二毛", "黑色");//{name: "二毛", color: "黑色"}
這種模式並不能看出來 cat1 和 cat2 是同一個原型對象的實例css
構造函數模式html
function Cat (name, color) { this.name = name; this.color = color; this.age = "5"; } var cat1 = new Cat("大毛", "黃色"); var cat2 = new Cat("二毛", "黑色"); cat1.constructor == Cat;//true cat2.constructor == Cat; //true cat1.constructor == cat2.constructor//true
cat1 instanceof Cat ;// true
function Cat (name, color) { this.name = name; this.color = color; } Cat.prototype.age = "10"; var cat1 = new Cat("大毛", "黃色"); var cat2 = new Cat("二毛", "黑色"); cat1.age; // 10; cat2.age; // 10;
// 建立父構造函數 function SuperClass(name){ this.name = name; this.showName = function(){ alert(this.name); } } // 設置父構造器的原型對象 SuperClass.prototype.Age = '123'; // 建立子構造函數 function SubClass(){} // 設置子構造函數的原型對象實現繼承 SubClass.prototype = SuperClass.prototype; //生成實例 var child = new SubClass() child.name // undefined child.Age // 123
//即 子構造函數.prototype = new 父構造函數() // 建立父構造函數 function SuperClass(){ this.name = 'HiSen'; this.age = 25; this.showName = function(){ console.log(this.name); } } // 設置父構造函數的原型 SuperClass.prototype.friends = ['js', 'css']; SuperClass.prototype.showAge = function(){ console.log(this.age); } // 建立子構造函數 function SubClass(){} // 實現繼承 SubClass.prototype = new SuperClass(); // 修改子構造函數的原型的構造器屬性,由於此時繼承了父構造函數指向 //SuperClass; 因此要修改一下。 SubClass.prototype.constructor = SubClass; //生成實例 var child = new SubClass();
console.log(child.name); // HiSen console.log(child.age);// 25 child.showName();// HiSen child.showAge();// 25 console.log(child.friends); // ['js','css'] // 當咱們改變friends的時候, 父構造函數的原型對象的也會變化 child.friends.push('html'); console.log(child.friends);// ["js", "css", "html"] var father = new SuperClass(); console.log(father.friends);// ["js", "css", "html"]
此時再看:發現子構造函數 不只繼承了父構造函數原型 prototype 上的成員,也繼承了其它成員。但是修改子構造函數的屬性時,咱們發現父構造函數的原型對象也對應修改,那有沒有辦法屏蔽這一種狀況呢 ? 接着往下看:數組
拷貝實現繼承函數
說到拷貝,可能會分深拷貝和淺拷貝,其實:this
淺拷貝是對象的屬性的引用,而不是對象自己; (淺拷貝只拷貝一層,若是存在多層仍是會影響原對象)spa
深拷貝是建立一個新的內存地址保存值 ; (與原對象互不影響)prototype
下邊我列舉兩個拷貝的方法來實踐一下:code
淺拷貝htm
例舉一個簡單的淺拷貝: 對象形式對象
function clone(source) { var target = {}; for(var i in source) { if (source.hasOwnProperty(i)) { target[i] = source[i]; } } return target; }
深拷貝
對象形式的深拷貝
function clone(source) { var target = {}; for(var i in source) { if (source.hasOwnProperty(i)) { if (typeof source[i] === 'object') { target[i] = clone(source[i]); // 注意這裏 } else { target[i] = source[i]; } } } return target; }
數組形式的深拷貝
function clone(source) { var out = [],i = 0,len = source.length; for (; i < len; i++) { if (source[i] instanceof Array){ out[i] = clone(arr[i]); } else out[i] = source[i]; } return out; }
固然出了以上這些實現繼承的方法之外還有更多的方式一樣能夠實現繼承,例如:
Object.create();繼承
Object.defineProperties()
的第二個參數同樣)。注意:該參數對象不能是
undefined
,另外只有該對象中自身擁有的可枚舉的屬性纔有效,也就是說該對象的原型鏈上屬性是無效的。
var obj = {
"a":'123', fun :function () { alert(1) } }
var jc = Object.create(obj); jc.a; //123 jc.fun();//1
咱們能夠看到,jc 繼承了 obj 的屬性;同時也繼承了 obj 對象的方法;
ES6鍾提供了一個方法 Object.assign();
方法能夠把任意多個的源對象自身的可枚舉屬性拷貝給目標對象,而後返回目標對象。Object.assign
是ES6的新函數。Object.assign()
Object.assign(target, ...sources)
target:目標對象。
sources:任意多個源對象。
var obj = { a: {a: "hello", b: 21} }; var initalObj = Object.assign({}, obj); initalObj.a.a = "changed"; console.log(obj.a.a); // "changed"
最後再說一種最簡單的方式,轉成字符串 - 再轉回來;
var obj1 = { o: { a: 1 } }; var obj2 = JSON.parse(JSON.stringify(obj1));