var colors = {
//...
};
複製代碼
function Person(name,age,job){
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function (){
console.log(this.name);
}
return o;
};
var person1 = Person('李雪峯','26','web前端開發');
var person2 = Person('hq','25','攝影師');
複製代碼
function Animal(name,color){
this.name = name;
this.color = color;
thia.sayName = function(){
console.log(this.name);
}
}
var dog = new Animal('旺財','黑色')
var dog2 = new Animal('阿拉斯加','黑白相間')
複製代碼
function Animal(){};
Animal.prototype.name = "旺財";
Animal.prototype.age = 3;
Animal.prototype.sayName = function(){
console.log(this.name);
};
var dog = new Animal();
dog.sayName(); //旺財
var dog2 = new Animal();
dog2.sayName(); //旺財
console.log(dog.sayName === dog2.sayName) //true
複製代碼
function Animal(name,age,color){
this.name = name;
this.age = age;
this.color = color;
this.friends = ['旺旺','旺財','二哈']
}
Animal.prototype.sayName = function(){
console.log('狗狗的名字叫:'+this.name);
}
var dog = new Animal('二狗子','3','黑色');
dog.friends.push('陳二狗'); //陳二狗被黑的最慘的一次
console.log(dog.friends)
console.log(dog.sayName())
var dog2 = new Animal('狗腿子','10','五光十色');
dog2.friends.push('走狗');
console.log(dog2.friends);
console.log(dog2.sayName())
console.log(dog.friends == dog2.friends) //false
console.log(dog.sayName == dog2.sayName) //true
複製代碼
function Person(name,age,job){
//屬性
this.name = name;
this.age = age;
this.job = job;
//方法
if(typeof this.sayName != 'function'){
Person.prototype.sayName = function(){
console.log(this.name);
}
}
}
var friend = new Person('李雪峯','26','web前端開發');
friend.sayName();
複製代碼
function Person(name,age,job){
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
console.log(this.name);
}
return o;
}
// 比工廠模式多了個new調用, 而且把Person叫作了構造函數
var friend = new Person('李學峯','26','web前端開發');
friend.sayName();
// 應用
function SpecialArray(){
//建立數組
var values = new Array();
//添加值
values.push.apply(values,arguments);
//添加方法
values.toPipedString = function(){
return this.join('||');
};
//返回數組
return values;
}
var colors = new SpecialArray('red','pink','orange','blue');
console.log(colors.toPipedString()); //red||pink||orange||blue
複製代碼
- 變量Person中保存的是一個穩妥對象,而除了調用sayName()
- 沒有別的方式能夠訪問其數據成員.
function Person(name,age,job){
// 建立要返回的對象
var o = new Object();
//能夠在這裏定義私有變量和函數
o.sayName = function(){
console.log(name);
}
return o;
}
var friend = Person('lxf','111','web');
friend.sayName();
複製代碼
原型鏈的概念: 其基本思想是利用原型讓一個引用類型繼承另外一個引用類型的屬性和方法前端
這裏要先說一下: 構造函數/原型/實例的關係web
每一個構造函數都有一個
原型對象
,原型對象都包含一個指向構造函數的指針 constructor
,而實例
都包含一個指向原型對象的內部指針[[proto]](__proto__)
.數組
假如咱們讓
原型對象
等於另外一個類型的實例
,結果就是,此時的原型對象
將包含一個指向另外一個另外一個原型的指針
bash
假如另外一個
原型
又是另外一個類型
的實例,那麼上述關係依然成立,如此層層遞進,就構成了實例與原型的鏈條
. 這就是所謂原型鏈的基本概念app
//實現一個原型鏈
function SuperType(){
this.property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property;
}
function SubType(){
this.subproperty = false;
}
//繼承了SuperType --> 一個函數的原型對象等於一個類型(函數)的實例
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function(){
return this.subproperty;
}
var instance = new SubType();
console.log(instance.getSuperValue)
複製代碼
instance.constructor
如今指向的是 SuperType
,這是由於原來 SubType.prototype 中的constructor 被重寫
的緣故實際上
,不是SubType的原型的 constructor 屬性被重寫了,而是 SubType 的原型指向了另外一個對象 SuperType 的原型
,而這個原型對象的 constructor 屬性指向的是 SuperType引用紅寶書中的圖片說明函數
經過實現原型鏈,本質上擴展了前面介紹的原型搜索機制,
當以讀取模式訪問一個實例屬性時
首先會在實例
中搜索該屬性.測試
若是,沒有找到該屬性,則會繼續搜索實例的原型.ui
在經過原型鏈實現繼承的狀況下,搜索過程就得沿着
原型鏈繼續向上
.this
上邊的例子中的搜索順序spa
引用紅寶書中的圖片說明
肯定原型和實例的關係
第一種:
instanceof
操做符這個操做符來測試實例與原型中出現過的構造函數,結果就會返回true
console.log(instance instanceof Object); //true
console.log(instance instanceof SubType); //true
console.log(instance instanceof SuperType); //true
複製代碼
因爲原型鏈的關係,能夠輸 instance 是 Object | SuperType | SubType 中任何類型的實例
第二種:
isPrototypeOf()方法
一樣,只要是
原型鏈中出現過的原型
,均可以說是該原型鏈所派生的實例的原型
console.log(Object.isPrototypeOf(instance)); // true
console.log(SuperType.isPrototypeOf(instance)); // true
console.log(SubType.isPrototypeOf(instance)); // true
複製代碼
原型鏈的問題
function SuperType(nane){
this.name = name;
this.colors = ['red','pink','orange','green'];
}
function SubType(nane,age){
SuperType.call(this); // 不傳遞參數的狀況
//SuperType.call(this,name); //傳遞參數
//SuperType.apply(this,arguments); // 傳遞參數
// 實例屬性
this.age = age;
}
var instance1 = new SubType();
instance1.colors.push('blue');
console.log(instance1.colors);
var instance2 = new SubType();
console.log(instance2.colors)
複製代碼
方法都在構造函數中定義,一次函數複用就無從談起.
function SuperType(name){
this.name = name;
this.colors = ['red','blue','pink'];
}
SuperType.prototype.sayName = function(){
console.log(this.name);
}
function SubType(name,age){
SuperType.call(this,name); //繼承實例屬性
this.age = age;
}
SubType.prototype = new SuperType(); //繼承方法
SubType.prototype.constructor = SubType; // 構造函數回指
SubType.prototype.sayAge = function (){
console.log(this.age);
}
var instane1 = new SubType('lixuefeng','26');
instane1.colors.push('green','222');
console.log(instane1.sayName())
console.log(instane1.sayAge())
console.log(instane1.colors)
var instane2 = new SubType('zhangyu','23');
instane2.colors.push('122','#fff');
console.log(instane2.sayName())
console.log(instane2.sayAge())
console.log(instane2.colors)
複製代碼
組合繼承避免了原型鏈和借用構造函數的缺陷,融合了他們的優勢,
instanceof
和isPrototypeOf()
也可以用於識別組合繼承建立的對象
function object(o){
function F(){};
F.prototype = o;
return new F();
}
// 應用
var person = {
name : 'lixuefeng',
friends:['red','pink','blue']
};
var anotherPerson = object(person);
anotherPerson.name = 'Greg';
anotherPerson.friends.push('Rob');
var yetAnotherPerson = object(person);
yetAnotherPerson.name = '你你你';
yetAnotherPerson.friends.push('#fff');
console.log(person.friends)
複製代碼
Object.create()
方法規範化了原型式繼承.Object.create()
與object()
方法的行爲相同一個參數的時候
var person = {
name : 'lixuefeng',
friends:['red','pink','blue']
};
var anotherPerson = Object.create(person);
anotherPerson.name = 'Greg';
anotherPerson.friends.push('Rob');
var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = '你你你';
yetAnotherPerson.friends.push('#fff');
console.log(person.friends)
複製代碼
兩個個參數的時候
var person = {
name : 'lixuefeng',
friends:['red','pink','blue']
};
var anotherPerson = Object.create(person,{
name:{
value:'<<離人愁>> ==> 李元傑'
}
});
console.log(anotherPerson.name)
複製代碼
function createAnother(original){
var clone = Object.create(original); // 經過調用函數建立一個新對象 返回一個傳入對象的新的實例賦值給 clone
clone.sayHi = function(){ // 以某種方式來加強這個對象
console.log('hi');
};
return clone; // 返回這個對象
}
var person = {
name : 'xxname',
friends:['red','blue','van']
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); // hi
anotherPerson.friends.push('11','sss')
console.log(anotherPerson.friends)
console.log(anotherPerson.name)
複製代碼
function SuperType(name){
this.name = name;
this.colors = ['red','blue','pink','orange'];
}
SuperType.prototype.sayName = function(){
console.log(this.name);
}
function SubType(name,age){
SuperType.call(this,name); // 這裏調用一次 SuperType()
//SuperType.apply(this,arguments)
this.age = age;
}
SubType.prototype = new SuperType(); // 這裏調用一次 SuperType()
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function (){
console.log(this.age);
}
var instance =new SubType('小明','100');
instance.colors.push('#333');
console.log(instance.sayName());
console.log(instance.sayAge());
console.log(instance.colors);
var instance2 = new SubType('小藍','122312');
instance2.colors.push('#fff','#ff0000');
console.log(instance2.sayName());
console.log(instance2.sayAge());
console.log(instance2.colors);
複製代碼
在第一次調用 SuperType
構造函數時,SubType.prototype
會獲得兩個屬性:
SuperType
的實例屬性,只不過如今位於 SubType
的原型中當調用SubType構造函數時,又會調用一次 SuperType構造函數,這一次又在新對象上建立了實例屬性 name
和 colors
因而,這兩個屬性就屏蔽了原型中的兩個同名屬性
寄生構造模式能夠解決這個問題
function inheritPrototype(subType,superType){
var prototype = Object.create(superType.prototype); // 建立對象
prototype.constructor = subType; // 加強對象
subType.prototype = prototype; // 指定對象
}
function SuperType(name){
this.name = name;
this.colors = ['red','blue','pink','orange'];
}
SuperType.prototype.sayName = function(){
console.log(this.name);
}
function SubType(name,age){
SuperType.call(this,name); // 這裏調用一次 SuperType()
//SuperType.apply(this,arguments)
this.age = age;
}
//SubType.prototype = new SuperType(); // 這裏調用一次 SuperType()
//SubType.prototype.constructor = SubType;
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge = function (){
console.log(this.age);
}
var instance =new SubType('小明','100');
instance.colors.push('#333');
console.log(instance.sayName());
console.log(instance.sayAge());
console.log(instance.colors);
var instance2 = new SubType('小藍','122312');
instance2.colors.push('#fff','#ff0000');
console.log(instance2.sayName());
console.log(instance2.sayAge());
console.log(instance2.colors);
複製代碼
這個例子只調用了一次
SuperType
構造函數,而且所以避免了在SubType.prototype
上面建立沒必要要的,多餘的屬性。於此同時,原型鏈還能保持不變。
所以,還可以正常使用
instanceof
和isPrototypeOf()
寄生組合式繼承是引用類型最理想的繼承範式
記錄理解,有不對的地方,歡迎指出
有趣好玩Games
推薦一些有趣好玩的小遊戲手機遊戲等