国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JS基礎(chǔ)篇--面向?qū)ο笈c原型

Pluser / 2688人閱讀

摘要:判斷一個(gè)對象是否指向該構(gòu)造函數(shù)的原型對象,可以使用方法來測試。如何讓指向呢直接強(qiáng)制指向即可運(yùn)行中重寫原型,不會(huì)保留之前原型的任何信息,把原來的原型對象和構(gòu)造函數(shù)對象的實(shí)例切斷了。

創(chuàng)建對象
var box = new Object();//創(chuàng)建對象
box.name = "Lee";      //添加屬性
box.age = 100;
box.run = function(){
    return this.name + this.age + "運(yùn)行中";  //this 表示當(dāng)前作用域下對象
}

// this 表示new Object()實(shí)例出來的那個(gè)對象
alert(box.run());

這就是創(chuàng)建對象最基本的方法,但是有個(gè)缺點(diǎn),想創(chuàng)建一個(gè)類似的對象,就會(huì)產(chǎn)生大量的代碼。

工廠模式

為了解決多個(gè)類似對象聲明的問題,我們可以使用一種叫做工廠模式的方法,這種方法就是為了解決實(shí)例化對象產(chǎn)生大量重復(fù)的問題。

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",20);
var box2 = createObject("Jack",30);
console.log(box1.run());
console.log(box2.run());

工廠模式解決了重復(fù)實(shí)例化的問題,但還有一個(gè)問題,那就是識(shí)別問題,因?yàn)楦緹o法搞清他們到底是哪個(gè)對象的實(shí)例。

alert(typeof box1); //Object
alert(box1 instanceof Object);//true
構(gòu)造函數(shù)

ECAMScript中采用構(gòu)造函數(shù)(構(gòu)造方法)可用來創(chuàng)建特定的對象。類似于Object對象。

//構(gòu)造函數(shù)
function Box(name,age){
    this.name = name;
    this.age = age;
    this.run = function(){
        return this.name + this.age +"運(yùn)行中...";
    };
};

var box1 = new Box("Lee",100);
var box2 = new Box("Jack",200);

console.log(box1.run());
console.log(box2.run());

使用構(gòu)造函數(shù)的方法,即解決了重復(fù)實(shí)例化的問題,又解決了對象識(shí)別的問題,但問題是,這里并沒有new Object(),為什么可以實(shí)例化Box(),這個(gè)是哪里來的呢?

使用了構(gòu)造函數(shù)的方法,和使用工廠模式的方法他們不同之處如下:
1.構(gòu)造函數(shù)方法沒有顯示的創(chuàng)建對象(new Objectt()),但它在后臺(tái)自動(dòng)var obj = new Object();
2.直接將屬性和方法賦值給this對象,this就相當(dāng)于obj;
3.沒有return語句,不需要返回對象引用,它是在后臺(tái)自動(dòng)返回的。

//構(gòu)造函數(shù)
function Box(name,age){
    this.name = name;
    this.age = age;
    this.run = function(){
        return this.name + this.age +"運(yùn)行中...";
    };
};

function Dack(name,age){
    this.name = name;
    this.age = age;
    this.run = function(){
        return this.name + this.age +"運(yùn)行中...";
    };
};

var box1 = new Box("Lee",100);
var box2 = new Box("Jack",200);
var box3 = new Dack("MrLee",300);

console.log(box1.run());
console.log(box2.run());
console.log(box3.run());

//解決了對象識(shí)別問題
console.log(box1 instanceof Box); //true
console.log(box2 instanceof Box); //true
console.log(box3 instanceof Box); //false
console.log(box3 instanceof Dack);//true

對象冒充:使用call()方法

var o= new Object();
Box.call(o,"Lee",100);
console.log(o.run());

看下一個(gè)問題:

 var box1 = new Box("Lee",100); //實(shí)例化后地址為1
 var box2 = new Box("Lee",100); //實(shí)例化后地址為2

 console.log(box1.name == box2.name); //true
 console.log(box1.age == box2.age);      //true
 console.log(box1.run() == box2.run());//true //構(gòu)造函數(shù)體內(nèi)的方法的值是相當(dāng)?shù)? console.log(box1.run == box2.run); //false //因?yàn)樗麄儽容^的是引用地址
 

上面的代碼運(yùn)行說明引用地址不一樣,那么構(gòu)造函數(shù)內(nèi)的方法也可以這樣寫:

this.run = new Function("return this.name + this.age +"運(yùn)行  

如何讓他們的引用地址一樣,下面代碼:

function Box(name,age){
    this.name = name;
    this.age = age;
    this.run = run;
};

function run(){
    return this.name +this.age+"運(yùn)行中...";
}
 var box1 = new Box("Lee",100); //實(shí)例化后地址為1
 var box2 = new Box("Lee",100); //實(shí)例化后地址為2
 console.log(box1.run == box2.run); //true //因?yàn)樗麄儽容^的是引用地址  
 

把構(gòu)造函數(shù)內(nèi)部的方法通過全局來實(shí)現(xiàn)引用地址一致。
雖然使用了全局函數(shù)run()來解決了保證引用地址一致的問題,但是這種方式又帶來了一個(gè)新的問題,全局中的this在對象調(diào)用的時(shí)候是Box本身,而當(dāng)普通函數(shù)調(diào)用的時(shí)候,this又代表window。

原型
function Box(){
       //構(gòu)造函數(shù)函數(shù)體內(nèi)什么都沒有,這里如有過,叫做實(shí)例屬性,實(shí)例方法
} 

Box.prototype.name="Lee"; //原型屬性
Box.prototype.age=100;
Box.prototype.run=function(){ //原型方法
    return this.name+this.age+"運(yùn)行中...";
}

var box1=new Box();
var box2=new Box();
console.log(box1.run == box2.run); //true
console.log(box1.prototype);//這個(gè)屬性是一個(gè)對象,訪問不到
console.log(box1.__proto__);//這個(gè)屬性是一個(gè)指針指向prototype原型對象。 

如果是實(shí)例方法,不同的實(shí)例化,他們的方法地址是不一樣的,是唯一的。
如果是原型方法,那么他們的地址是共享的,大家都一樣。

console.log(box1.constructor); //構(gòu)造屬性,可以獲取構(gòu)造函數(shù)  

PS:IE瀏覽器在腳本訪問__proto__會(huì)不能識(shí)別,火狐和谷歌及其他某些瀏覽器能識(shí)別。雖然可以輸出,但是無法獲取內(nèi)部信息。

判斷一個(gè)對象是否指向該構(gòu)造函數(shù)的原型對象,可以使用isPrototypeOf()方法來測試。

console.log(Box.prototype.isPrototypeOf(box1)); //true //只要實(shí)例化對象,即都會(huì)指向

原型模式的執(zhí)行流程:
1.先查找構(gòu)造函數(shù)實(shí)例里的屬性或方法,如果有,立刻返回;
2.如果構(gòu)造函數(shù)實(shí)例里沒有,則去它的原型對象里找,如果有,就返回。

如何判斷屬性時(shí)構(gòu)造函數(shù)的實(shí)例里,還是原型里?可以使用hasOwnProperty()函數(shù)來驗(yàn)證:

console.log(box1.hasOwnProperty("name"));//如果實(shí)例里有返回true,否則返回false  

如何判斷屬性是原型里的?

function Box(){
       
} 

Box.prototype.name="Lee"; //原型屬性
Box.prototype.age=100;
Box.prototype.run=function(){ //原型方法
    return this.name+this.age+"運(yùn)行中...";
}

function isProperty(object,property){
    return !object.hasOwnProperty(property) && (property in object);
}
var box1=new Box();
console.log(isProperty(box1,"name"));

為了讓屬性和方法更好的體現(xiàn)封裝的效果,并且減少不必要的輸入,原型的創(chuàng)建可以使用字面量的方式

使用字面量的方式創(chuàng)建原型對象,這里的{}就是對象,是object,new Object就相當(dāng)于{}

function Box(){} 

Box.prototype={
    name:"Lee",
    age:100,
    run:function(){
        return this.name+this.age+"運(yùn)行中...";
    }
}

var box = new Box();
console.log(box.constructor == Box); //false 

字面量創(chuàng)建的方式使用constructor屬性不會(huì)指向?qū)嵗鴷?huì)指向Object,構(gòu)造函數(shù)創(chuàng)建的方式則相反。
這里的Box.prototype={}就相當(dāng)于創(chuàng)建了一個(gè)新的對象,所以 box.constructor是Object。
如何讓box.constructor指向Box呢?

function Box(){} 

Box.prototype={
    constructor:Box,//直接強(qiáng)制指向即可
    name:"Lee",
    age:100,
    run:function(){
        return this.name+this.age+"運(yùn)行中...";
    }
}

var box = new Box();
console.log(box.constructor == Box); //true

重寫原型,不會(huì)保留之前原型的任何信息,把原來的原型對象和構(gòu)造函數(shù)對象的實(shí)例切斷了。

function Box(){} 

Box.prototype={
    constructor:Box,
    name:"Lee",
    age:100,
    run:function(){
        return this.name+this.age+"運(yùn)行中...";
    }
}

//重寫原型
Box.prototype={
    age:200
}
var box = new Box();
console.log(box.name); //undefined

查看sort是否是Array原型對象里的方法
alert(Array.prototype.sort);

在如下 判斷String原型對象里是否有substring方法
alert(String.prototype.substring);

給String 添加addstring方法:

String.prototype.addstring=function(){
    return this+",被添加了!";
}
var box="Lee";
console.log(box.addstring());

注:原型模式創(chuàng)建對象也有自己的缺點(diǎn),它省略了構(gòu)造函數(shù)傳參初始化這一過程,帶來的缺點(diǎn)就是初始化的值都是一致的。而原型最大的缺點(diǎn)就是它最大的優(yōu)點(diǎn),那就是共享。

原型中所有屬性是被很多實(shí)例共享的,共享對于函數(shù)非常合適,對于包含基本值的屬性也還可以。但如果屬性包含引用類型,就存在一定的問題:

function Box(){}

Box.prototype={
    constructor:Box,
    name:"Lee",
    age:100,
    family:["哥哥","姐姐","妹妹"],
    run:function(){
        return this.name+this.age+"運(yùn)行中...";
    }
};

var box1 = new Box();
console.log(box1.family); //"哥哥","姐姐","妹妹"
box1.family.push("弟弟");
console.log(box1.family);//"哥哥","姐姐","妹妹","弟弟"

var box2 = new Box();
console.log(box2.family);//"哥哥","姐姐","妹妹","弟弟"

從上面代碼可以看出,在第一個(gè)實(shí)例修改后引用類型,保持了共享。box2.family共享了box1添加后的引用類型的原型。

為了解決構(gòu)造傳參和共享問題,可以組合構(gòu)造函數(shù)+原型模式:

function Box(name,age){  //保持獨(dú)立的用構(gòu)造函數(shù)
    this.name=name;
    this.age=age;
    this.family=["哥哥","姐姐","妹妹"];
}

Box.prototype={ //保持共享的用原型
    constructor:Box,
    run:function(){
        return this.name+this.age+"運(yùn)行中...";
    }
}

var box1 = new Box("Lee",100);
console.log(box1.family); //"哥哥","姐姐","妹妹"
box1.family.push("弟弟");
console.log(box1.family);//"哥哥","姐姐","妹妹","弟弟"



var box2 = new Box("Jack",200);
console.log(box2.family); //"哥哥","姐姐","妹妹" //引用類型沒有使用原型,所以沒有共享

動(dòng)態(tài)原型模式

//把原型封裝到構(gòu)造函數(shù)里
function Box(name,age){
    this.name=name;
    this.age=age;
    this.family=["哥哥","姐姐","妹妹"];

    console.log("原型初始化開始");  //執(zhí)行了兩次
    Box.prototype.run=function(){
        return this.name+this.age+"運(yùn)行中...";
    }
    console.log("原型初始化結(jié)束"); //執(zhí)行了兩次
}

//原型的初始化,只要第一次初始化就可以了,沒必要每次構(gòu)造函數(shù)實(shí)例化的時(shí)候都初始化
var box1 = new Box("Lee",100);
var box2 = new Box("Jack",200);

為了只讓第一次初始化,那么就判斷

function Box(name,age){
    this.name=name;
    this.age=age;
    this.family=["哥哥","姐姐","妹妹"];

    if(typeof this.run!="function"){
        console.log("原型初始化開始"); //執(zhí)行了一次次
        Box.prototype.run=function(){
            return this.name+this.age+"運(yùn)行中...";
        };
        console.log("原型初始化結(jié)束"); //執(zhí)行了一次
    }
}

//原型的初始化,只要第一次初始化就可以了,沒必要每次構(gòu)造函數(shù)實(shí)例化的時(shí)候都初始化
var box1 = new Box("Lee",100);
var box2 = new Box("Jack",200);

寄生構(gòu)造函數(shù)
如果以上都不能滿足需要,可以使用一下寄生構(gòu)造函數(shù)。
寄生構(gòu)造函數(shù)=工廠模式+構(gòu)造函數(shù)

function Box(name,age){
    var obj = new Object();
    obj.name=name;
    obj.age=age;
    obj.run=function(){
        return this.name+this.age+"運(yùn)行中...";
    }
    return obj;
}

var box1 = new Box("Lee",100);
var box2 = new Box("Jack",200);

穩(wěn)妥構(gòu)造函數(shù)

在一些安全的環(huán)境中,比如禁止使用this和new,這里的this是構(gòu)造函數(shù)里不使用的this,這里的new是在外部實(shí)例化構(gòu)造函數(shù)時(shí)不使用new。這種創(chuàng)建方式叫做穩(wěn)妥構(gòu)造函數(shù)。

function Box(name,age){
    var obj = new Object();
    obj.name=name;
    obj.age=age;
    obj.run=function(){
        return this.name+this.age+"運(yùn)行中...";
    }
    return obj;
}

var box1 = Box("Lee",100);
var box2 = Box("Jack",200);

繼承

繼承是面向?qū)ο笾幸粋€(gè)比較核心的概念。其它正統(tǒng)面向?qū)ο笳Z言都會(huì)用兩種方式實(shí)現(xiàn)繼承:一個(gè)是接口實(shí)現(xiàn),一個(gè)是繼承。而ECMAScript只支持繼承,不支持接口實(shí)現(xiàn),而實(shí)現(xiàn)繼承的方式依靠原型鏈完成。

function Box(){
    this.name="Lee";
}

function Jack(){
    this.age=100;
}

Jack.prototype = new Box();

var jack = new Jack();
console.log(jack.name); //Lee

為了解決引用共享和超類型無法傳參的問題,我們采用一種叫借用構(gòu)造函數(shù)的技術(shù),或者成為對象冒充(偽造對象、經(jīng)典繼承)的技術(shù)解決這兩個(gè)問題。

function Box(name){
    this.name=name;
}

Box.prototype.age=200;

function Jack(name){
    Box.call(this,name);
}

var jack = new Jack("Lee");

console.log(jack.name);//Lee
console.log(jack.age);//undefined   

但是上面的代碼可以看出,對象冒充沒有繼承原型鏈上的age屬性。所以要繼承Box的原型,就出現(xiàn)下面的組合繼承。
組合繼承即是原型鏈+借用構(gòu)造函數(shù)的模式

function Box(name){
    this.name=name;
}

Box.prototype.age=200;

function Jack(name){
    Box.call(this,name);
}

Jack.prototype = new Box();

var jack = new Jack("Lee");

console.log(jack.name);//Lee
console.log(jack.age);//200

原型式繼承

//臨時(shí)中轉(zhuǎn)函數(shù)
function obj(o){
    function F(){};
    F.prototype = o;
    return new F();
}

//這是字面量的聲明方式,相當(dāng)于var box = new Box();
var box={
    name:"Lee",
    age:100,
    family:["哥哥","姐姐","妹妹"]
};

var box1 = obj(box);
console.log(box1.family);//"哥哥","姐姐","妹妹"
box1.family.push("弟弟");
console.log(box1.family);//"哥哥","姐姐","妹妹","弟弟"

var box2 = obj(box);
console.log(box2.family);//"哥哥","姐姐","妹妹","弟弟"

存在的問題就是引用類型共享了。

寄生式繼承
把原型式與工廠模式結(jié)合起來。

//臨時(shí)中轉(zhuǎn)函數(shù)
function obj(o){
    function F(){};
    F.prototype = o;
    return new F();
}


//寄生函數(shù)
function create(o){
    var f=obj(o);
    f.run=function(){
        return this.name+"方法";
    }
    return f;
}


//這是字面量的聲明方式,相當(dāng)于var box = new Box();
var box={
    name:"Lee",
    age:100,
    family:["哥哥","姐姐","妹妹"]
};

var box1 = create(box);
console.log(box1.run());

寄生組合繼承

//臨時(shí)中轉(zhuǎn)函數(shù)
function obj(o){
    function F(){};
    F.prototype = o;
    return new F();
}


//寄生函數(shù)
function create(box,desk){
    var f=obj(box.prototype);
    f.constructor=desk; //調(diào)整原型構(gòu)造指針
    desk.prototype=f;
}


function Box(name,age){
    this.name=name;
    this.age=age;
}

Box.prototype.run=function(){
    return this.name+this.age+"運(yùn)行中...";
}

function Desk(name,age){
    Box.call(this,name,age); //對象冒充
}

//通過寄生組合繼承來實(shí)現(xiàn)繼承
create(Box,Desk); //這句話用來替代Desk.prototype = new Box();

var desk = new Desk("Lee",100);
console.log(desk.run());

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/78845.html

相關(guān)文章

  • 【連載】前端個(gè)人文章整理-從基礎(chǔ)到入門

    摘要:個(gè)人前端文章整理從最開始萌生寫文章的想法,到著手開始寫,再到現(xiàn)在已經(jīng)一年的時(shí)間了,由于工作比較忙,更新緩慢,后面還是會(huì)繼更新,現(xiàn)將已經(jīng)寫好的文章整理一個(gè)目錄,方便更多的小伙伴去學(xué)習(xí)。 showImg(https://segmentfault.com/img/remote/1460000017490740?w=1920&h=1080); 個(gè)人前端文章整理 從最開始萌生寫文章的想法,到著手...

    madthumb 評論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對象”還好嗎?

    摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍(lán)圖或原型。在中,對象通過對類的實(shí)體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    李昌杰 評論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對象”還好嗎?

    摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍(lán)圖或原型。在中,對象通過對類的實(shí)體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    Lyux 評論0 收藏0
  • SegmentFault 技術(shù)周刊 Vol.32 - 七夕將至,你的“對象”還好嗎?

    摘要:很多情況下,通常一個(gè)人類,即創(chuàng)建了一個(gè)具體的對象。對象就是數(shù)據(jù),對象本身不包含方法。類是相似對象的描述,稱為類的定義,是該類對象的藍(lán)圖或原型。在中,對象通過對類的實(shí)體化形成的對象。一類的對象抽取出來。注意中,對象一定是通過類的實(shí)例化來的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 馬上就要到七夕了,離年底老媽老爸...

    AaronYuan 評論0 收藏0
  • javascript基礎(chǔ):關(guān)于js面向對象的理解

    摘要:關(guān)于中面向?qū)ο蟮睦斫饷嫦驅(qū)ο缶幊趟且环N編程思想我們的編程或者學(xué)習(xí)其實(shí)是按照類實(shí)例來完成的學(xué)習(xí)類的繼承封裝多態(tài)封裝把實(shí)現(xiàn)一個(gè)功能的代碼封裝到一個(gè)函數(shù)中一個(gè)類中以后再想實(shí)現(xiàn)這個(gè)功能,只需要執(zhí)行這個(gè)函數(shù)方法即可,不需要再重復(fù)的編寫代碼。 關(guān)于js中面向?qū)ο蟮睦斫?面向?qū)ο缶幊?oop) 它是一種編程思想 (object-oriented programming ), 我們的編程或者學(xué)習(xí)其...

    roadtogeek 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<