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

資訊專欄INFORMATION COLUMN

進(jìn)擊的 JavaScript(八) 之 繼承

ddongjian0000 / 998人閱讀

摘要:也就是說(shuō),并不知道,等是屬于哪個(gè)對(duì)象的哪個(gè)構(gòu)造函數(shù)或者類。構(gòu)造函數(shù)模式與原型模式相結(jié)合的模式。給新建的對(duì)象,添加屬性,建立與構(gòu)造函數(shù)之間的聯(lián)系。另一種就是構(gòu)造函數(shù)繼承了。

前面講完原型鏈,現(xiàn)在來(lái)講繼承,加深理解下。

一、對(duì)象的相關(guān)知識(shí)

什么是對(duì)象? 就是一些無(wú)序的 key : value 集合, 這個(gè)value 可以是 基本值,函數(shù),對(duì)象。(注意 key 和 value 之間 是冒號(hào) : ,每個(gè) key : value 之間 是逗號(hào) , )

var person = {
    name: "zdx",
    age: 18,
    get: function(){
        return "名字:" + this.name + "年紀(jì):" + this.age;
    }
}

這時(shí)的 person 就是一個(gè)對(duì)象

讀取對(duì)象的屬性,有兩種方式:點(diǎn)[" "],(使用中括號(hào),里面是有引號(hào)的)

person.name   //"zdx"
person["age"]    //18

之前說(shuō)過(guò),對(duì)象的創(chuàng)建 有三種 方式: 字面量,new,Object.create;

但是,這種簡(jiǎn)單的創(chuàng)建,并不能滿足,我們實(shí)際開(kāi)發(fā)的要求。

比如,每個(gè)人的名字,年紀(jì)不一樣,我們不可能,每個(gè)人都寫一個(gè)對(duì)象,那不得炸了。

var personA = {
    name: "A",
    age: 28
}

var personB = {
    name: "B",
    age: 22
}

所以,這時(shí)候,我們就需要一些創(chuàng)建模式。


(一)、工廠模式

工廠模式呢,就是我們寫一個(gè)方法,然后通過(guò)這個(gè)方法復(fù)制出我們需要的對(duì)象。我們需要多少個(gè),就復(fù)制多少個(gè)。(注意這里是用方法(函數(shù)) 來(lái)生成對(duì)象)

var createPerson = function(name,age){
    var obj = {},
    obj.name = name,
    obj.age = age
}

然后我們就可以這樣使用了。

var personA = createPerson("A", 28);
var personB = createPerson("B", 22);

但是呢,這種模式,創(chuàng)建的對(duì)象,無(wú)法歸類。也就是說(shuō),并不知道 personA,personB 等 是 屬于哪個(gè)對(duì)象的(哪個(gè)構(gòu)造函數(shù)或者類)。

具有相同特性的一類事物,把它總結(jié)成一個(gè) ;比如,人類,有男人,女人,小孩。把他們總結(jié)成了人類。

比如:

var obj = {};
obj instanceof Object;    //true
//instanceof  方法 可以判斷 前者是否是 后者的實(shí)例對(duì)象

var arr = [];
arr instanceof Array;    //true

于是,構(gòu)造函數(shù)模式來(lái)了。


(二)、構(gòu)造函數(shù)模式(類)

要想知道,男人,女人 屬于什么類, 人類? 獸類? 這時(shí)候就需要 構(gòu)造函數(shù)(類)了。

function Person(name, sex){     //注意,我們通常把構(gòu)造函數(shù)(類)的首字母大寫!
    this.name = name;
    this.sex = sex;
}
var personA = new Person("張三", "男");
var personB = new Person("李四", "女");

console.log( personA instanceof Person );    //true
console.log( personB instanceof Person );    //true

這時(shí)候 創(chuàng)建出來(lái)的對(duì)象, 就知道 它屬于哪個(gè)構(gòu)造函數(shù)(類)了。


這里為啥用了 this 呢?new 一個(gè)函數(shù), 為啥會(huì)創(chuàng)建出 一個(gè)實(shí)例對(duì)象(我們把 new 出來(lái)的對(duì)象 稱為 實(shí)例對(duì)象,簡(jiǎn)稱實(shí)例)呢?

這步,之前的原型鏈中說(shuō)過(guò),如果你懂了,可以簡(jiǎn)單過(guò)一眼,增強(qiáng)記憶。

這個(gè)呢,就要理解new 到底干了啥呢:

新建一個(gè)對(duì)象;

將該對(duì)象,即實(shí)例指向構(gòu)造函數(shù)的原型;

將構(gòu)造函數(shù)的this,指向該新建的對(duì)象;

返回該對(duì)象,即返回實(shí)例。下面,手寫一個(gè)方法 實(shí)現(xiàn)new 的功能。


function New(func){    //func 指?jìng)鬟M(jìn)來(lái)的構(gòu)造函數(shù)
    var obj = {};   //這里就直接新建一個(gè)空對(duì)象了,不用new Object了,效果一樣的,因?yàn)槲腋杏X(jué)這里講實(shí)現(xiàn)new的功能   再用 new 就不太好。
    
    if(func.prototype != null){
        obj.__proto__ = func.prototype;
    }
  
    func.apply(obj,Array.prototype.slice.call(arguments, 1));
    //把func構(gòu)造函數(shù)里的this 指向obj對(duì)象(你可以理解成func構(gòu)造函數(shù)的this 替換成 obj對(duì)象);
    //Array.prototype.slice.call(arguments, 1);這個(gè)就是把New 函數(shù),func 之后傳進(jìn)來(lái)的參數(shù),轉(zhuǎn)成數(shù)組。
   //把該參數(shù)數(shù)組,傳入func構(gòu)造函數(shù)里,并執(zhí)行func構(gòu)造函數(shù),比如:屬性賦值。

    return obj;
    
}

驗(yàn)證下:

function Person(name, sex){
    this.name = name;
    this.sex = sex;
    this.getName = function(){
        return this.name;
    }
}

var p = New(Person,"周大俠啊", "男");

console.log( p.getName() );   //"周大俠啊"

console.log( p instanceof Person );    //true

去掉new 的寫法就是這樣:

function Person(name, sex){
    var obj = {};
    obj.__proto__ = Person.prototype;
    obj.name = name;
    obj.sex = sex;
    obj.getName = function(){
        return obj.name;
    }
    return obj;
}

var p = Person("周大俠啊", "男");

console.log( p.getName() );   //"周大俠啊"

console.log( p instanceof Person );    //true


使用 new 就簡(jiǎn)化了步驟。

這種模式,也有弊端,你看出來(lái)了嗎? 有木有發(fā)現(xiàn),每個(gè)實(shí)例對(duì)象 都有 相同 的 getName 方法,這樣,是不是就但占資源了呢,100個(gè)實(shí)例對(duì)象,就新建了 100 個(gè) getName 方法。

原型模式開(kāi)始!


(三)、原型模式

之前的原型鏈說(shuō)過(guò),屬性、方法的讀取是沿著原型鏈查找的,也就是說(shuō),在構(gòu)造函數(shù)的原型對(duì)象上 創(chuàng)建的 屬性、方法,它的實(shí)例對(duì)象都能夠使用。

function Person(){};
Person.prototype.name = "周大俠啊";
Person.prototype.sex = "男";
Person.prototype.getName  = function(){
    return Person.prototype.name;
}

var p = new Person();
console.log( p.getName() );   //"周大俠啊"
console.log( p.hasOwnProperty("getName") );   //false   getName 不是 p實(shí)例的屬性

這樣,創(chuàng)建的實(shí)例對(duì)象 都能使用 getName ,并且,也不會(huì)給每個(gè)實(shí)例對(duì)象,添加該屬性。

不過(guò),你發(fā)現(xiàn)了嗎,這樣創(chuàng)建的實(shí)例對(duì)象,都是固定的屬性值, 一更改,所有的實(shí)例對(duì)象獲取的值,也都改變了。

那么說(shuō)了半天,這都是啥呢,別急,正因?yàn)樯厦孀龅匿亯|,才有更好的 方法。我覺(jué)得,眼尖的同學(xué),可能已經(jīng)知道了。


構(gòu)造函數(shù)模式 與 原型模式 相結(jié)合的模式。

構(gòu)造函數(shù)模式,可以創(chuàng)建 每個(gè) 實(shí)例對(duì)象 自己的屬性, 而原型模式,可以共享,同一個(gè)方法。

所以,我們一般,把對(duì)象自己的屬性、方法 ,用構(gòu)造函數(shù)模式創(chuàng)建; 公共的方法,用原型模式 創(chuàng)建。

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

Person.prototype.getName = function(){
    return this.name;
}

var p = new Person("周大俠啊", 22);
p.getName();


這樣就可以完美的創(chuàng)建對(duì)象了。

要是你有余力,可以想想,這里的 this.namethis 是怎么回事。

但是,上面這個(gè)還可以優(yōu)化,要是 Person.prototype 上有很多方法, 這種寫法就很不好,一般,我們用這種寫法:

function Person(name, age){
    this.name = name;
    this.age = age;
}
//新建一個(gè)對(duì)象,給該對(duì)象添加 方法, 然后把該對(duì)象 賦值給Person.prototype ,該對(duì)象就成為 Person (構(gòu)造函數(shù))的原型對(duì)象了。

Person.prototype = {
    constructor : Person,   //給新建的對(duì)象,添加constructor 屬性,建立與構(gòu)造函數(shù)之間的聯(lián)系。
    getName : function(){
        return this.name;
    },
    getAge : function(){
        return this.age;
    }
}

var p = new Person("周大俠啊", 22);

p.getName();


這里的 this 又看懂是怎么回事了嗎? 那我就簡(jiǎn)單說(shuō)一下 this 的知識(shí)吧。

關(guān)于 this 估計(jì)都聽(tīng)說(shuō)過(guò) 誰(shuí)調(diào)用它,this就指向誰(shuí),這種說(shuō)法,不嚴(yán)謹(jǐn),this 的指向,是 在函數(shù)調(diào)用(運(yùn)行)時(shí)確定的!

上面的:

Person.prototype = {
    constructor : Person, 
    getName : function(){
        return this.name;
    },
}
var p = new Person("周大俠啊", 22);
p.getName();

thisgetName 函數(shù)里,而getName 真正運(yùn)行 的地方 是 p.getName,p 是調(diào)用者,所以, this 就指向 p(換句話說(shuō),這時(shí)的this 就是 p)。

你要理解 精髓, 函數(shù)調(diào)用(運(yùn)行)時(shí) 確定的調(diào)用者 之間的關(guān)系。

看這個(gè):

var a = 10;
var b = {
    a : 20,
    say : function(){
        console.log(this.a);
    }
}

var c = b.say;
c();    //10   非嚴(yán)格模式下,獨(dú)立調(diào)用(無(wú)調(diào)用者)this 指向全局對(duì)象

包含 this 的函數(shù) 正在調(diào)用(運(yùn)行) 的時(shí)候 是 c(); 此時(shí),無(wú)調(diào)用者,指向全局對(duì)象。




二、繼承

上面做了辣么多鋪墊,終于要開(kāi)始繼承的講解啦!什么是繼承呢,其實(shí)呢,就是你 想要使用 別人的屬性,或者方法; 這時(shí)候就要利用繼承來(lái)實(shí)現(xiàn)。

既然是 得到別人的屬性,方法,就是繼承,那么不就是 除了 Object.prototype 其他都是繼承了? dui ! 你說(shuō)的沒(méi)錯(cuò)...哈哈

所以,繼承的一種就是基于 原型鏈的了 ,就是屬性的查找,讀取。

另一種就是 構(gòu)造函數(shù)繼承了。

首先來(lái)一個(gè)需要被繼承的目標(biāo)

//父類:
function Person(name) {
    this.name = name;
}

Person.prototype = {
    constructor: Person,
    getName : function() {
        return this.name;
    }
}


(一)、構(gòu)造函數(shù)的繼承
//子類:
function Son(name, age) {   
    Person.call(this, name);    //call 方法,把前面函數(shù)的this 指向 給定的對(duì)象,第二個(gè)參數(shù)開(kāi)始,傳入 參數(shù),并執(zhí)行函數(shù)。
    this.age = age;
}

//就相當(dāng)于
function Son(name, age) {
    //Person(name); 此時(shí) Person 里的 this  等于當(dāng)前的this
    this.age = age;
}

//等同于
function Son(name, age) {
    this.name = name,
    this.age = age
}

下面檢驗(yàn)一下:

var s1 = new Son("周大俠啊", 22);
console.log(s1.name);  //"周大俠啊" 
console.log(s1.getName());   //報(bào)錯(cuò),這是Person原型對(duì)象上的方法


(二)、原型鏈的繼承 1、通過(guò)new一個(gè)父類實(shí)例

這種是,new 一個(gè)父類實(shí)例,然后把son.prototype 添加到原型鏈上去。

//new 一個(gè) Person 實(shí)例 賦給 Son.prototype
Son.prototype = new Person();

//給子類的原型加方法:
Son.prototype.get = function() {
        return this.name + this.age;
}

上面的 Son.prototype = new Person() 實(shí)際上就是這樣的

//內(nèi)部就是
var obj = {};

obj.__proto__ = Person.prototype;

Son.prototype = obj

//把 obj 賦給 Son.prototype 。而obj 這個(gè)實(shí)例  又指向了Person的原型對(duì)象,
//這樣,Son 就添加到了 Person 的原型鏈上了。


所以:

//給子類的原型加方法:
Son.prototype.get = function() {
        return this.name + this.age;
} 

//就是:
obj.get = function(){    //通過(guò)給obj添加方法 然后賦值給Son的原型對(duì)象
    return this.name + this.age;
};

驗(yàn)證:

var s2 = new Son("周大俠啊", 22);

console.log(s2.get());  //"周大俠啊22" 

console.log(s2.getName());   //"周大俠啊"


2、于是乎,我們就可以自己封裝一個(gè)繼承方法
function create(proto, options){     //proto表示父類的原型對(duì)象,options表示給子類添加的屬性
    var obj = {};
    obj.__proto__ = proto;
    return Object.defineProperties(obj,options);    //Object.defineProperties方法直接在一個(gè)對(duì)象上定義新的屬性或修改現(xiàn)有屬性,并返回該對(duì)象。所以這里就直接return了
    }
    
//繼承  就這樣寫了
Son.prototype = create(Person.prototype,{
    constructor: {    //這種格式的賦值寫法, 是 defineProperties 方法規(guī)定的寫法。
        value: Son
    },
    get: {
        value: function(){
            return this.name + this.age;
        }
    }
})

//驗(yàn)證一下
var s3 = new Son("zdx",22);

console.log(s3.getName());     //"zdx"

console.log(s3.get());         //"zdx22"

Object.defineProperties具體用法點(diǎn)這里


3、ES5中就有個(gè)Object.create 方法 它就實(shí)現(xiàn)了剛剛封裝的create 方法

這里是它具體用法

可以直接使用它來(lái)完成繼承:

Son.prototype = Object.create(Person.prototype,{
    constructor: {
        value: Son
    },
    get: {
        value: function(){
            return this.name + this.age;
        }
    }
})

//驗(yàn)證一下
var s4 = new Son("zdx",22);

console.log(s4.getName());     //zdx

console.log(s4.get());         //zdx22

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

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

相關(guān)文章

  • JS面向?qū)ο蠖?this/原型鏈/new原理

    摘要:情況沒(méi)有明確作用對(duì)象的情況下,通常為全局對(duì)象例如函數(shù)的回調(diào)函數(shù),它的就是全局對(duì)象。正因如此,機(jī)器可以作為這類對(duì)象的標(biāo)志,即面向?qū)ο笳Z(yǔ)言中類的概念。所以機(jī)器又被稱為構(gòu)造函數(shù)。原型鏈也就是繼承鏈。 JS面向?qū)ο蠖?this/原型鏈/new原理 阮一峰JavaScript教程:面向?qū)ο缶幊?阮一峰JavaScript教程:實(shí)例對(duì)象與 new 命令 阮一峰JavaScript教程:this 關(guān)...

    anRui 評(píng)論0 收藏0
  • 進(jìn)擊JavaScript(四)原型與原型鏈

    摘要:每一個(gè)由構(gòu)造函數(shù)創(chuàng)建的對(duì)象都會(huì)默認(rèn)的連接到該神秘對(duì)象上。在構(gòu)造方法中也具有類似的功能,因此也稱其為類實(shí)例與對(duì)象實(shí)例一般是指某一個(gè)構(gòu)造函數(shù)創(chuàng)建出來(lái)的對(duì)象,我們稱為構(gòu)造函數(shù)的實(shí)例實(shí)例就是對(duì)象。表示該原型是與什么構(gòu)造函數(shù)聯(lián)系起來(lái)的。 本文您將看到以下內(nèi)容: 傳統(tǒng)構(gòu)造函數(shù)的問(wèn)題 一些相關(guān)概念 認(rèn)識(shí)原型 構(gòu)造、原型、實(shí)例三角結(jié)構(gòu)圖 對(duì)象的原型鏈 函數(shù)的構(gòu)造函數(shù)Function 一句話說(shuō)明什么...

    XBaron 評(píng)論0 收藏0
  • 進(jìn)擊 JavaScript(一) 類型轉(zhuǎn)換

    摘要:實(shí)際上,我們通常認(rèn)為是自有類型的唯一成員。比較運(yùn)算符的操作數(shù)可能是任意類型。結(jié)果只有,例得到操作值等價(jià)的布爾值真值為,假值為等同于,經(jīng)常稱為強(qiáng)制轉(zhuǎn)換。結(jié)果返回布爾值的用法是中唯一一個(gè)不等于任何值的包括它自己。 說(shuō)起 js 類型轉(zhuǎn)換,都是頭疼吧,暈暈的,但是不行啊,這東西很重要滴! 基礎(chǔ)知識(shí) JavaScript的數(shù)據(jù)類型分為六種,分別為null, undefined, boolean,...

    Scholer 評(píng)論0 收藏0
  • 進(jìn)擊 JavaScript(四) 閉包

    摘要:此時(shí)產(chǎn)生了閉包。導(dǎo)致,函數(shù)的活動(dòng)對(duì)象沒(méi)有被銷毀。是不是跟你想的不一樣其實(shí),這個(gè)例子重點(diǎn)就在函數(shù)上,這個(gè)函數(shù)的第一個(gè)參數(shù)接受一個(gè)函數(shù)作為回調(diào)函數(shù),這個(gè)回調(diào)函數(shù)并不會(huì)立即執(zhí)行,它會(huì)在當(dāng)前代碼執(zhí)行完,并在給定的時(shí)間后執(zhí)行。 上一節(jié)說(shuō)了執(zhí)行上下文,這節(jié)咱們就乘勝追擊來(lái)搞搞閉包!頭疼的東西讓你不再頭疼! 一、函數(shù)也是引用類型的。 function f(){ console.log(not cha...

    Anleb 評(píng)論0 收藏0
  • 進(jìn)擊 JavaScript (七) 原型鏈

    摘要:創(chuàng)建一個(gè)新的對(duì)象即實(shí)例對(duì)象把新對(duì)象的指向后面構(gòu)造函數(shù)的原型對(duì)象。簡(jiǎn)單來(lái)驗(yàn)證一下等同與對(duì)象沒(méi)有原型對(duì)象的原型對(duì)像等同于構(gòu)造函數(shù)是等同于,構(gòu)造函數(shù)是七原型鏈的作用其實(shí),原型鏈的根本作用就是為了屬性的讀取。 首先說(shuō)一下,函數(shù)創(chuàng)建的相關(guān)知識(shí) 在JavaScript中,我們創(chuàng)建一個(gè)函數(shù)A(就是聲明一個(gè)函數(shù)), 那么 js引擎 就會(huì)用構(gòu)造函數(shù)Function來(lái)創(chuàng)建這個(gè)函數(shù)。所以,所有的函數(shù)的con...

    ivydom 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

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