原型
1.定義:
原型是function對象的一個屬性般码,它定義了構(gòu)造函數(shù)制造出的對象的公共祖先仁烹。通過該構(gòu)造函數(shù)產(chǎn)生的對象候齿,可以繼承該原型的屬性和方法。原型也是對象瞳筏。
例如:
function Someone() { };
var someone1 = new Someone();
var someone2 = new Someone();
Someone.prototype --原型對象
Someone.prototype={ } 是祖先:由Someone這個構(gòu)造函數(shù)制造出的對象(someone1,someone2等 )的祖先稚瘾。每new一次,都產(chǎn)生新的對象姚炕,這些對象都繼承該原型的屬性和方法摊欠。
2.利用原型特點和概念,可以提取共有屬性柱宦。
// 提取共有祖先:
Car.prototype.height = 1400;
Car.prototype.lang = 4900;
Car.prototype.carName = "BMW";
function Car(color, uesr) {
// this.height = 1400;
// this.lang = 4900;
// this.carName = 'BMW';
this.color = color;
this. uesr = uesr;
}
var car = new Car('red', 'David');
var car1 = new Car('orange', 'Kangkang');
3對象和原型的增刪
對象的增刪(接上段代碼)
car.weight = '50 kg';
delete car.color; //對象的屬性刪除了
console.log(car.color) //undefined
console.log(car1.color) //orange
原型的增刪(接上段代碼)
console.log(car1.lang) // 4900
delete car1.lang; // car1.lang=4900.car1的lang的屬性值是原型上的值些椒,因此如果要刪除lang的值 也是要在原型上刪除。
console.log(car1.lang) // 4900
delete Car.prototype.lang;
console.log(car.lang); // undefined
console.log(car1.lang); // undefined掸刊、
4對象查看原型 — > 隱式屬性 proto免糕。
5.對象如何查看對象的構(gòu)造函數(shù) — > constructor
constructor 是查看對象的構(gòu)造函數(shù)
Teacher.prototype.key = "abc";
function Teacher(name) {
// var this={ __proto__:Teacher.prototype};
this.name = name;
this.subject = 'English';
};
var student1 = new Teacher('David');
var student2 = new Teacher('Kangkang');
console.log(Teacher);
// function Teacher(name) {this.name = name;this.subject = 'English'; }
console.log(student1);
// {name: "David", subject: "English" , _proto__: Objectc ————>onstructor: function Teacher(name) { this.name = name; this.subject = 'English'; }, __proto__: Object}
console.log(student1.__proto__);
// {key: "abc",constructor: function Teacher(name) { this.name = name; this.subject = 'English'; }, __proto__: Object}
console.log(student1.key); // "abc"
var OMB = {
key: '123',
}
student1.__proto__ = OMB; // {key: "123", __proto__: Object}
console.log(student1.__proto__);
console.log(student1.key); //"123"
案例1:更改了屬性值
Person.prototype.name = 'sunny';
function Person() { }
var person = new Person();
console.log(person.name); //"sunny"
Person.prototype.name = 'cherry';
console.log(person.name); //"cherry"
案例2 :更改對象。
Person1.prototype.name = 'sunny1';
function Person1() {
// var this={__proto__:Person1.prototype}; 每次new 一個對象時 才會有這樣的隱式語句忧侧。
}
var person1 = new Person1(); // 在function Person1{ 隱式的執(zhí)行 var this={__proto__:Person1.prototype};}
console.log(person1.name); //"sunny1"
console.log(person1);
Person1.prototype = {
name: 'cherry1'
};
console.log(person1.name); // "sunny1"
console.log(person1);
解析案例二:
Person1.prototype.name="sunny1";
由構(gòu)造函數(shù)Person1而來的新建對象的 --proto--:Person1.prototype;
Person1.prototype={ name:"cherry1"}
Person1.prototype 是原型對象的名字石窑,是個指針,卻不能完全指代對象全部內(nèi)容蚓炬。
剛開始由構(gòu)造函數(shù)Person1制造的對象person1有個屬性是_ --proto--,它的值是:指針名字叫Person1.prototype的原型對象松逊。后來這個指針不在指向原型對象,指向新建的{name:"cherry1"}對象肯夏。
但是由構(gòu)造函數(shù)Person1制造的對象person1的屬性是 --proto--卻還是指向原型對象经宏,不會因此改變指向。
容易犯錯:
Person1.prototype.name = 'sunny1';
function Person1() {}驯击;
Person1.prototype = {name: 'cherry1'};
var person1 = new Person1();
//在function Person1{ 隱式的執(zhí)行 var this={__proto__:Person1.prototype};}
console.log(person1.name); //cherry1
難點: Person.prototype constructor --proto-- 三者之間的聯(lián)系
原型鏈
1烁兰,如何構(gòu)成原型鏈?,
2,原型鏈上屬性的增刪改查
3徊都,誰調(diào)用的方法內(nèi)部this就是誰-原型案例
4沪斟,對象的最終都會繼承自O(shè)bject.prototype(不是所有 因為null 不會繼承Object.prototype)
5,object.create(原型);
6碟贾,原型方法上的重寫
構(gòu)成原型鏈的案例(1 傳統(tǒng)繼承)
function Grand() {};
var grand = new Grand();
Father.prototype = grand;
function Father() {
this.name = 'xuming';
this.fortune = {
card1: 'visa',
};
this.num = 100;
};
var father = new Father();
Son.prototype = father;
function Son() {
this.hobbit = 'smoke';
}
var son = new Son();
console.log(son.hobbit); //smoke
console.log(son.name); //xuming
son.fortune.card2 = 'master';
// son 依然沒有fortune屬性币喧。調(diào)用son.fortune對象的引用值為他添加card2的屬性并附值轨域。
son.num++;
console.log(son.num);
// 101 son.num=son.num+1;取過來自身+1袱耽;但是無法修改father的值
console.log(father.num); //100
案例:qian 每次調(diào)用 eat 方法的 weight對應(yīng)的值 都會+1
Qian.prototype = {
weight: 150,
}
function Qian() {
this.eat = function() {
this.weight++;
}
}
var qian = new Qian();
console.log(qian); //{eat:fn}
console.log(qian.weight); //150 原型上面有weight 這個屬性值
qian.eat();
console.log(qian.weight) //151 新對象qian每次調(diào)用一個eat方法,
Object.create(原型) Object.create(null) //()內(nèi)必須寫對象或者null 否則會報錯)
undefined null 這兩個都是原始值沒有原型對象 (Objec.creat(null)也沒有原型對象干发,除了這三個 其他都有)因此不能調(diào)用toString 方法
下面案例解析:
anotherObject 的原型是 myObject朱巨,但是由此方法創(chuàng)建的對象卻沒有。prototype和constructor枉长。因此此類對象無法用 instanceof(A instanceof B →A的constrcutor值是不是B冀续,)
anotherObject = {
a:2
};
var myObject = Object.create( anotherObject, {
b: {
enumerable: false,
writable: true,
configurable: false,
value: 3
},
c: {
enumerable: true,
writable: false,
configurable: false,
value: 4
}
});
myObject.hasOwnProperty( "a" ); // false hasOwnProperty判斷是否是自己的直接屬性
myObject.hasOwnProperty( "b" ); // true
myObject.hasOwnProperty( "c" ); // true
myObject.a; // 2
myObject.b; // 3
myObject.c; //4
var obj = Object.create(null)
console.log(obj); // {} No prototypies
obj.name = "王二麻子";
console.log(obj); // {name :"王二麻子"}
obj.__proto__ = {
age: 123
};
console.log(obj);
//{ name :"王二麻子",__proto__:Object,——>{age:123,__proto__:Object}}
console.log(obj.age); //undefined
.call(object,,,) apply(object,[ ]) 改變函數(shù)的this指向
區(qū)別是傳參列表不一樣琼讽,call只能傳實參,需要把實參按照形參的個數(shù)傳進去洪唐,apply只能傳一個數(shù)組形式的參數(shù)
利用別的函數(shù)實現(xiàn)自己的功能钻蹬,能夠減少代碼量 。
應(yīng)用案例:(2借用構(gòu)造函數(shù) 繼承)
function Model(name, color, age) {
this.name = name;
this.color = color;
this.age = age;
}
function Example(name, color, age, user, brand) {
Model.call(this, name, color, age);
//利用Model實現(xiàn)Examplef的功能凭需,讓Model內(nèi)的this 指向了call()內(nèi)的對象this(這個this其實指的是Example構(gòu)造函數(shù)構(gòu)造的新對象))Model的參數(shù)還能正常傳參數(shù)问欠。
//
this.user = user;
this.brand = brand;
}
var living = new Example('王者', 'red', 18, 'I', '名牌')
關(guān)于繼承,
1.傳統(tǒng)形式:過多的繼承了沒用的屬性
比如:
Grand.prototype.name = "ji";
function Grand(){}
var grand = Grand();
Son.prototype = grand;
function Son(){}
var son = new Son();
2.借用構(gòu)造函數(shù):不能繼承借用構(gòu)造函數(shù)的原型粒蜈,每次構(gòu)造函數(shù)都要多走一個函數(shù)顺献。
3.共享原型不能隨便改動自己的原型。
Father.prototype.lastName = "Q";
function Father(){}
function Son(){}
Son.prototype = Father.prototype;
var son = new Son();
var father = new Father();
function extend(Baby, Parent){
Baby.prototype = Parent.prototype;
}
4.圣杯模式
function inherit(Target, Origin) {
function F() {};
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constuctor = Target;
Target.prototype.uber = Origin.prototype;
}
Father.prototype.Lastname = "趙錢孫李"
function Son() {}
function Father() {}
inherit(Son, Father)
var son = new Son();
var father = new Father();
// son.__proto__ ——>new F()————>new F().__proto__ ————> Father.prototype 此時son.constructor:function Father(){};
// 此時new F() 雖然為son的原型對象 但是非定義在全局的作用域內(nèi) 因此無法顯示枯怖。
YUI 雅虎
圣杯模式的源碼注整,優(yōu)化繼承,子不干父
var Inherit = (function() {
var F = function() {}; //私有化變量 無法識別訪問
return function(Target, Origin) {
F.prototype = Origin.prototype;
Target.prototype = new F();
Target.prototype.constuctor = Target;
Target.prototype.uber = Origin.prototype;
}
}());
運用閉包防止全局變量污染度硝,模塊化開發(fā)
function Deng(name, wife) {
var prepareWife = " 趙小姐"; //私有化變量 無法訪問
this.name = name;
this.wife = wife;
this.divorce = function() {
this.wife = prepareWife;
}
this.sayPreparewife = function() {
console.log(prepareWife);
}
}
var deng = new Deng('鄧先生', '等太太');