標籤: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物件導向,原型,繼承