javascript面向對象和原型————呱呱二號
面向對象
1、工廠模式
function createObject(name,age){ let obj = new Object(); this.name = name; this.age = age; return obj; } let objA = createObject(‘Tom‘,24); let objB = createObject(‘Jane‘,23); typeof ObjA; //Object typeof ObjB; //Object ObjA instanceof Object; ObjA instanceof Object;//方法缺點:不能區分對象實例,所有對象實例都由Object實例化
2、構造函數模式
function Box(name,age){ this.name = name; this.age = age; this.run = function (){ return this.name + this.age; } } function Desk(name,age){ this.name = name; this.age = age; this.run = function (){ return this.name + this.age; } } let box= new Box(‘Tom‘,24); let desk = new Desk(‘Jane‘,23); box instanceof Box; //true box instanceof Desk; //false desk instanceof Desk; //true // //知識延伸,對象冒充 let o = new Object(); Box.call(o,‘Ha‘,25); o.name;
構造函數方式和原型方式變量存儲的方式
3、原型
我們創建的每一個函數都有一個prototype(原型屬性),這個屬性是一個對象,它的用途是包含可以由特定類型的所有實例共享的屬性和方法。邏輯上可以這麽理解:prototype通過調用構造函數而創建的那個對象的原型對象。使用原型的好處可以讓所有對象實例共享它所包含的屬性和方法。也就是說,不必在構造函數中定義對象信息,而是可以直接將這些信息添加到原型中。(我自己的理解,通過構造函數創建的對象會自動創建一個原型對象prototype。)
function Box(){}
Box.prototype.name = ‘Lee‘; //原型屬性
Box.prototype.age = 100;
Box.prototype.run = function () { //原型方法
return this.name + this.age + ‘運行中‘;
}
證明:原型對象內的屬性和方法都被實例對象共用
let box1 = new Box();
let box2 = new Box();
Object.is(box1.run,box2.run); //true Object.is(),判斷兩個變量是否相等 (等於box1.run === box2.run);
說明box1和box2中的run方法都指向同一個引用地址。
在原型模式聲明中,多了兩個屬性,這兩個屬性都是創建對象時自動生成的。__proto__屬性是實例指向原型對象的一個指針,它的作用就是指向構造函數的原型屬性constructor。通過這兩個屬性,就可以訪問到原型裏的屬性和方法了。
//判斷一個實例對象是否指向了原型對象,只要實例化了,會自動指向的
Box.prototype.isPrototypeOf(box1); //true 接著上面的代碼
let obj = new Object(); //
Box.prototype.isPrototypeOf(obj);
如果實例對象中有name屬性,原型對象中也有name屬性,通過 . 訪問name會打印處實例對象中的name屬性。
function Box () {}
Box.prototype.name = ‘guaguaerhao‘;
let box1 = new Box();
box1.name = ‘呱呱二號‘;
console.log(box1.name); //呱呱二號
原型模式的執行流程:
1、先查找實例對象中是否存在屬性,如果存在,則返回
2、如果實例對象中沒有該屬性,則在原型對象中查找,如果存在,則返回
判斷實例中是否存在屬性
box1.hasOwnProperty(‘name‘); //true
(name in box1) //不管是原型中有name屬性還是實例中有name屬性,都會返回true
判斷只有原型中是否存在屬性
function hasPrototypeProperty(object,property){
return !object.hasOwnProperty(property) && (property in object);
}
4、字面量原型模式
function Box () {}
Box.prototype = {
constructor: Box, //將原型對象的constructor強制指向回Box
name: ‘guaguaerhao‘,
age: 24,
run: function(){
return this.name + this.age;
}
}
ps:原型中最大的缺點就是它的優點,共享。原型模式創建的對象,省略了構造函數傳參,帶來的缺點就是初始化的值都是一樣的。
5、構造函數加原型模式(構造函數和方法分開,沒有一種封裝的感覺,感覺很零碎)
function Box(name,age){ //不共享的使用構造函數
this.name = name;
this.age = age;
this.family = [‘爸爸‘,‘媽媽‘,‘哥哥‘,‘我‘];
}
Box.prototype = { //共享的使用原型
constructor: Box,
run: function () {
return this.name + this.age;
}
}
6、動態原型模式
function Box(name,age){
this.name = name;
this.age = age;
//可是,實例化對象的時候,每次都會創建run()方法,浪費內存,因為他在每一個對象中都是一樣的功能,沒有必要,每次實例化都創建,實際上只需要創建一次。
Box.prototype.run = function () {
return this.name + this.age;
}
}
所以
function Box(name,age){
this.name = name;
this.name = age;
if(typeof this.run !== ‘function‘){ //只會實例化一次
Box.prototype.run = function () {
return this.name + this.age;
}
}
}
7、寄生構造函數(工廠模式+構造函數)
function Box(name,age){
let obj = new Object();
obj.name = name;
obj.age = age;
obj.run = function (){
return this.name + this.age;
}
return obj;
}
let obj = new Box(‘ha‘,24);
obj.run();
7、寄生構造函數(工廠模式+構造函數)
function Box(name,age){
let obj = new Object();
obj.name = name;
obj.age = age;
obj.run = function (){
return this.name + this.age;
}
return obj;
}
let obj = Box(‘ha‘,24);
obj.run();
繼承
1、繼承是面向對象中比較核心的概念,ECMAScript只支持繼承:
function Parent(){
this.name = ‘p‘;
}
function Child(){
this.name = ‘c‘;
}
//通過原型鏈繼承,父類實例化後的對象實例,賦值給子類型的原型屬性
//new Parent()會將構造函數裏的信息和原型的信息都交給Child
Child.prototype = new Parent();
2、對象冒充模式
為了解決引用共享和超類型無法傳參的問題,采用一種叫借用構造函數的技術,或者成為對象冒充
function Parent(name,age){
this.name = name;
this.age = age;
}
//Parent.prototype.family = ‘家庭‘; //child實例無法訪問
function Child(name,age){
Parent.call(this,name,age); //對象冒充,給父類傳遞參數,對象冒充只能繼承構造函數中的屬性,原型中的無法訪問
}
let child = new Child(‘haha‘,24);
child.name;
child.family; //undefined
3、原型鏈加借用構造函數,組合模式
function Parent(age){
this.age = age;
}
Parent.prototype.run = function () { //解決了方法共享
return this.age;
}
function Child(age){
Parent.call(this,age);
}
Child.prototype = new Parent();
javascript面向對象和原型————呱呱二號