JS物件導向,原型,繼承

來源:互聯網
上載者:User

標籤:substring   子類   prototype   列印   聲明   多次   win   .so   刪除   


ECMAScript有兩種開發模式:1.函數式(過程化),2.物件導向(OOP)。物件導向的語言有一個標誌,那就是類的概念,而通過類可以建立任意多個具有相同屬性和方法的對象。但是,ECMAScript沒有類的概念,因此它的對象也與基於類的語言中的對象有所不同。
var box = new Object();
box.name = ‘Lee‘;
box.age = 100;
box.run = function()
{
return this.name + this.age + ‘運行中...‘; //this表示當前範圍下的對象,即new Object()執行個體化出來的那個對象,this要放在一個範圍下。比如box.run(){}。
}
alert(box.run());

alert(this.name); //這裡的this 代表window


原廠模式 解決了重複執行個體化的問題,但是無法識別對象
function createObject(name,age)
{
var obj = new Object(); //建立對象
obj.name = name; //添加屬性
obj.age = age;
obj.run = function(){
return this.name + this.age + ‘運行中...‘;
};
return obj; //返回對象引用
}

var box1 = createObject(‘Lee‘,100);
var box2 = createObject(‘Jack‘,200);
alert(box1.run());
alert(box2.run());

alert(typeof box1);
alert(typeof box2);


建構函式建立對象
function Box(name,age){ //建立一個對象,所有建構函式的對象其實就是Object
this.name = name; //添加一個屬性
this.age = age;
this.run = function(){ //添加一個方法
return this.name + this.age + ‘運行中...‘;
};
};
function Desk(name,age){ //建立一個對象,所有建構函式的對象其實就是Object
this.name = name; //添加一個屬性
this.age = age;
this.run = function(){ //添加一個方法
return this.name + this.age + ‘運行中...‘;
};
};
//1.建構函式沒有new Object,但它後台會自動var obj = new Object
//2.this就相當於obj
//3.建構函式不需要返回對象引用,它是後台自動返回的

//1.建構函式也是函數,但函數名第一個字母大寫
//2.必須new建構函式名();new Box(),而這個Box第一個字母也是大寫的。
//3.必須使用new運算子。
var box1 = new Box(‘Lee‘,100);
var box2 = new Box(‘Jack‘,200);
var box3 = new Desk(‘kkk‘,500);
alert(box1.run());
alert(box2.run());
alert(box1 instanceof Box);
alert(box2 instanceof Box);
alert(box3 instanceof Desk);

 

原型
function Box(){} //建構函式函數體內什麼都沒有,這裡如果有,叫做執行個體屬性,執行個體方法
Box.prototype.name = ‘Lee‘; //原型屬性
Box.prototype.age = 100; //原型屬性
Box.prototype.run = function(){ //原型方法
return this.name + this.age + ‘運行中...‘;
};
var box1 = new Box();
var box2 = new Box();
alert(box1.name);
alert(box1.run());

//如果是執行個體方法,不同的執行個體化,它們的方法地址是不一樣的,是唯一的。
//如果是原型方法,那麼它們的地址是共用的。
//alert(box1.run == box2.run);  //地址共用,因為box1和box2的run方法都屬於Box的原型方法
//alert(box1.prototype); //這個屬性是一個對象,訪問不到
//alert(box1.__proto__); //這個屬性是一個指標指向prototype原型對象,IE瀏覽器不支援這個屬性,列印不出來
//alert(box1.constructor); //構造屬性,可以擷取建構函式本身。作用是被原型指標定位,然後得到建構函式本身。其實就是對象執行個體對應的原型對象的作用。

//判斷一個對象執行個體(對象引用)是不是指向了原型對象,基本上,只要執行個體化,他自動指向的。
//alert(Box.prototype.isPrototypeOf(box1));

//var obj = new Object();
//alert(Object.prototype.isPrototypeOf(obj));

//原型模式的執行流程
//1.先尋找建構函式執行個體裡的屬性或方法,如果有,立刻返回;
//2.如果建構函式執行個體裡沒有,則去它的原型對象裡找,如果有,就返回。
//box1.name = ‘Jack‘; //執行個體屬性,並沒有重寫原型屬性,就近原則
//alert(box1.name);
//alert(box2.name); //執行個體屬性不會共用,所以box2訪問不到執行個體屬性,只能訪問原型屬性
//delete box1.name; //刪除執行個體中的屬性
//delete Box.prototype.name; //刪除原型中的屬性
//Box.prototype.name = ‘KK‘; //覆蓋原型中的屬性
//alert(box1.name);

//box1.name = ‘KAC‘
//alert(box1.hasOwnProperty(‘name‘)); //判斷執行個體中是否存在指定屬性
//alert(‘name‘ in box1); //不管執行個體屬性或者原型屬性是否存在,只要有就返回true

//判斷只有原型中存在屬性
//function isProperty(object,property){
//return !object.hasOwnProperty(property) && (property in object)
//}
//alert(isProperty(box1,‘name‘));

function Box(){};
var box = new Box();
alert(box.prototype); //使用對象執行個體無法訪問到prototype
alert(box.__proto__); //使用對象執行個體訪問prototype的指標
alert(Box.prototype); //使用建構函式名(對象名)訪問prototype


//使用字面量的方式建立原型對象
function Box(){};
//這裡{}就是對象,是Object,new Object就相當於{}
Box.prototype = {
constructor:Box, //強制指向Box
name:‘Lee‘,
age:100,
run:function(){
return this.name + this.age + ‘運行中...‘;
}
};
//使用字面量的方式建立的原型對象會導致constructor指向Object而不是Box
字面量方式建立原型對象的constructor之所以會指向Object是因為Box.prototype={};
這種寫法其實就是建立了一個新對象。而每建立一個函數,就會同時建立它的prototype,
這個對象也會自動擷取constructor屬性。所以,新對象的constructor重寫了Box原來的constructor
因此會指向新對象,而新對象沒有指定建構函式,那麼就是指向Object。

//重寫了原型對象
Box.prototype = {
age:200; //這裡不會保留之前原型的任何資訊了。把原來的原型對象和建構函式對象執行個體之前的關係切斷了。
}
var box = new Box();
//alert(box.constructor == Box);
alert(box.age);

//數組排序
var box = [5,1,6,9,3,5,8,1];
alert(box.sort());

//查看sort是否是Array原型對象裡的方法
alert(Array.prototype.sort);
//查看substring是否是String原型對象裡的方法
alert(String.prototype.substring);

//內建參考型別的功能擴充
String.prototype.addstring = function(){
return this + ‘,被添加了!‘;
};
var box = ‘Lee‘;
alert(box.addstring());


//原型缺點
function Box(){}
Box.prototype={
constructor:Box,
name:‘Lee‘,
age:100,
family:[‘gege‘,‘jiejie‘,‘meimei‘],
run:function(){
return this.name + this.age + ‘運行中...‘
}
};
var box1 = new Box();
alert(box1.family);
box1.family.push(‘didi‘); //在第一個執行個體修改後參考型別,保持了共用
alert(box1.family);
var box2 = new Box();
alert(box2.family); //共用了box1添加後的參考型別的原型


//為瞭解決構造傳參和共用問題,可以組合建構函式+原型模式
function Box(name,age){
this.name = name;
this.age = age;
this.family = [‘gege‘,‘jiejie‘,‘meimei‘];
}
Box.prototype = {
constructor:Box,
run:function(){
return this.name + this.age + ‘運行中...‘;
}
};
var box1 = new Box(‘Kee‘,100);
alert(box1.family);
box1.family.push(‘didi‘);
alert(box1.family);
var box2 = new Box(‘lee‘,200);
alert(box2.family); //參考型別沒有使用原型,所以沒有共用


//動態原型模式,可以將原型封裝到建構函式裡。封裝性更好
function Box(name,age){
this.name = name;
this.age = age;
this.family = [‘gege‘,‘jiejie‘,‘meimei‘];

if(typeof this.run != ‘function‘){ //判斷this.run是否存在
//alert(‘KS‘)
Box.prototype.run = function(){
return this.name + this.age + ‘運行中...‘;
};
//alert(‘JS‘);
}
}
//原型的初始化,只要第一次初始化就可以了,沒必要每次建構函式執行個體化的時候都初始化
var box1 = new Box(‘Kee‘,100);
var box2 = new Box(‘lee‘,200);


//寄生建構函式 原廠模式+建構函式
function Box(name,age){
var obj = new Object();
obj.name = name;
obj.age = age;
obj.run = function(){
return this.name + this.age + ‘運行中...‘;
};
return obj;
}
var box1 = new Box(‘Lee‘,100);
alert(box1.run());
var box2 = new Box(‘Jack‘,200);
alert(box2.run());


//穩妥建構函式
function Box(name,age){
var obj = new Object();
obj.name = name;
obj.age = age;
obj.run = function(){
return this.name + this.age + ‘運行中...‘;
};
return obj;
}
var box1 = Box(‘Lee‘,100);
alert(box1.run());
var box2 = Box(‘Jack‘,200);
alert(box2.run());


//繼承,通過原型鏈實現
function Box(){ //被繼承的函數叫做超類型(父類,基類)
this.name = ‘Lee‘;
}
Box.prototype.name = ‘Jack‘;
function Desk(){ //繼承的函數叫做子類型(子類,衍生類別)
this.age = 100;
}
function Table(){
this.level = ‘AAAAAA‘;
}
//通過原型鏈繼承,超類型執行個體化後的對象執行個體,賦值給予類型的原型屬性
//new Box()會將Box構造裡的資訊和原型裡的資訊都交給Desk
//Desk的原型,得到的是Box的構造+原型裡的資訊
Desk.prototype = new Box(); //通過原型鏈繼承
Table.prototype = new Desk();
var desk = new Desk();
var table = new Table();
alert(desk.age);
alert(desk.name); //就近原則,執行個體裡有,就返回,沒有就去原型尋找
alert(table.level);
//子類型從屬於自己或者其他的超類型
alert(desk instanceof Desk);
alert(desk instanceof Box);
alert(box instanceof Desk);


//使用對象冒充繼承
function Box(name,age){
this.name = name;
this.age = age;
this.family = [‘GEGE‘,‘JIEJIE‘,‘MEIMEI‘]; //參考型別,放在構造裡就不會被共用
}
Box.prototype.family = ‘jiating‘;
function Desk(name,age){
Box.call(this,name,age) //對象冒充,只能繼承構造裡的資訊
}
var desk = new Desk(‘Lee‘,100);
alert(desk.name);
alert(desk.family);


//原型鏈+借用建構函式的模式,這種模式稱為組合繼承,解決了複用的問題
function Box(name,age){
this.name = name;
this.age = age;
this.family = [‘GEGE‘,‘JIEJIE‘,‘MEIMEI‘];
}
Box.prototype.run = function(){
return this.name + this.age + ‘運行中...‘;
}
//建構函式裡的方法,放在建構函式裡,每次執行個體化,都會分配一個記憶體位址,浪費空間.最好放在原型裡,保證多次執行個體化只有一個地址
function Desk(name,age){
Box.call(this,name,age) //對象冒充
}
Desk.prototype = new Box(); //原型鏈繼承
var desk = new Desk(‘Lee‘,100);
alert(desk.run());


//原型式繼承:這種繼承藉助原型並基於已有的對象建立新對象,同時還不會因此建立自訂類型。
//臨時中轉函數
function obj(o){ //o表示將要傳遞進入的一個對象
function F(){} //F構造是一個臨時建立的對象,用來儲存傳遞過來的對象
F.prototype = o; //將o對象執行個體賦值給F構造的原型對象
return new F(); //最後返回這個得到傳遞過來對象的對象執行個體
}
//F.prototype = 0其實就相當於Desk.prototype = new Box();
//這是字面量的聲明方式,相當於var box = new Box();
var box = {
name:‘Lee‘,
age:100,
family:[‘gege‘,‘jiejie‘,‘meimei‘]
};
//box1就等於new F();
var box1 = obj(box);
//alert(box1.name);
alert(box1.family);
box1.family.push(‘didi‘);
alert(box1.family);
var box2 = obj(box);
alert(box2.family); //參考型別的屬性共用了


//寄生式繼承 = 原型式+原廠模式
function obj(o){
function F(){}
F.prototype = o;
return new F();
}
//寄生函數
function create(o){
var f = obj(o);
f.run = function(){
return this.name + ‘方法‘;
}
return f;
}
var box = {
name:‘Lee‘,
age:100,
family:[‘gege‘,‘jiejie‘,‘meimei‘]
};
var box1 = create(box);
alert(box1.run());


//寄生組合繼承
function obj(o){
function F(){}
F.prototype = o;
return new F();
}
//寄生函數
function create(box,desk){
var f = obj(box.prototype);
f.constructor = desk; //調整原型構造指標
desk.prototype = f;
}
function Box(name,age){
this.name = name;
this.age = age;
}
Box.prototype.run = function(){
return this.name + this.age + ‘ssssss‘;
}
function Desk(name,age){
Box.call(this,name,age); //對象冒充
}
//通過寄生組合繼承來實現繼承
create(Box,Desk); //這個用來替代Desk.prototype = new Box();
var desk = new Desk(‘Lee‘,100);
alert(desk.run());
alert(desk.constructor);

 

JS物件導向,原型,繼承

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.