構(gòu)造函數(shù)的繼承

1. 包裝對象

非空對象可以添加屬性或者方法

var arr = [];
arr.a = 10;
alert(arr.a);

但是基本數(shù)據(jù)類型也有自身的方法和屬性五督,這些屬性是如何調(diào)用的呢拆又?

var str = "abc";
str.charAt(1);

當(dāng)嘗試去調(diào)用簡單類型的屬性或者方法的時候,這個數(shù)據(jù)類型會找到自身的構(gòu)造函數(shù)身上的屬性或者方法,返回查找的屬性或方法之后,構(gòu)造函數(shù)自動銷毀。這個過程叫做包裝對象。

那么上面的字符串調(diào)用方法的過程就是這樣:

var str = "abc";
str.charAt(1);
str -> str的構(gòu)造函數(shù) String -> 找到charAt方法并調(diào)用 ->銷毀這個new String

2.hasOwnProperty

作用:
判斷參數(shù)是否為自身的私有屬性
語法:

obj/fn.hasOwnProperty(屬性名)洽洁;

返回值為Boolean
如果是調(diào)用者自身的私有屬性,返回true懒鉴,否則返回false
注意诡挂,判斷的參數(shù)只能是調(diào)用者 自身 的私有屬性,如果是它的原型或者原型鏈上的屬性也會返回false

function fn1(name){
    this.name = name;
}
fn1.prototype.age = function(){
    console.log(1);
}
var f1 = new fn1('cat');

console.log(fn1.hasOwnProperty('name'));        //true
console.log(fn1.hasOwnProperty('age'));         //false
console.log(fn1.prototype.hasOwnProperty('age'))    //true

3.constructor

作用:
查看某個對象的構(gòu)造函數(shù)是誰

當(dāng)一個對象實例化之后临谱,瀏覽器會為它自動加上這個屬性璃俗。
constructor很容易被修改。當(dāng)構(gòu)造函數(shù)的原型賦值對象的時候悉默,那么constructor就被修改了城豁,指向Object

這個方法可以手動修正constructor指向(指向正確的構(gòu)造函數(shù)的名稱)。

4. instanceof

作用:
這是一個二元運(yùn)算符
可以用來判斷左邊的實例化對象是不是右邊的構(gòu)造函數(shù)構(gòu)造出來的
語法:

t2 instanceof t1

t2:實例化對象
t1:構(gòu)造函數(shù)

返回值:
返回一個Boolean抄课,如果t2是t1構(gòu)造出來的唱星,返回true雳旅,否則返回false

5. call,apply

這兩個方法都是改變函數(shù)中this的指向
語法:

函數(shù)名.call(this指向的對象间聊,函數(shù)的參數(shù)1攒盈,函數(shù)的參數(shù)2,···函數(shù)的參數(shù)n)哎榴;

函數(shù)名.apply(this指向的對象型豁,[函數(shù)的參數(shù)1,函數(shù)的參數(shù)2尚蝌,···,函數(shù)的參數(shù)n])

call方法有無限個參數(shù)迎变,其中第一個參數(shù)是想要個改變的this指向,剩下的參數(shù)是函數(shù)的實參

apply方法有2個參數(shù)飘言,其中給第一個參數(shù)是想要改變的那個this指向衣形,第二個參數(shù)是一個數(shù)組,數(shù)組中的每一項數(shù)據(jù)都是函數(shù)的實參

function fn1(a,b){
    alert(a+b);
    alert(this);
}
fn1.call(document,2,3);
fn1.apply(document,[1,2]);

6.繼承

6.1 拷貝繼承

原理:
屬性繼承 + 方法繼承
如果有一個構(gòu)造函數(shù)init姿鸿,這個時候需要繼承這個init

那么可以創(chuàng)建一個構(gòu)造函數(shù)init2谆吴,調(diào)用init,修改init2的this指向苛预,這樣就可以完成屬性繼承(使用call或者apply方法)纪铺、
那么接下來我們要完成的是方法繼承
如果直接讓

init2.prototype = init.prototype;

由于構(gòu)造函數(shù)的原型是是一個對象,是引用類型數(shù)據(jù)碟渺。由JS的數(shù)據(jù)類型的存放我們可以知道,如果這樣寫突诬,只是把init的prototype的地址指向復(fù)制給了init2的prototype苫拍,這樣如果對init2的prototype進(jìn)行修改的話,init的prototype也會同步進(jìn)行修改旺隙。因為他們指向的是同一個對象绒极。
所以我們需要使用for··in對init的prototypr進(jìn)行遍歷,逐一取出它的方法賦值給init2的prototype蔬捷,這樣就可以是兩個prototype指向不同的對象垄提,兩個原型互不干涉。這樣就完成了一次拷貝繼承周拐。

function Init(){
    this.name = "a";
}
Init.prototype.a = function(){
    console.log("這是原型a");
};

//拷貝繼承
function Init2(){
    Init.call(this);
}
for(var attr in Init.prototype){
    Init2.prototype[attr] = Init.prototype[attr];
}
Init2.prototype.b = function(){
    console.log("這回是init2的原型B铡俐,Init1沒有");
};

var in1 = new Init();
var in2 = new Init2();
in2.a();
in2.b();
in1.b();    //這個會報錯

6.2 類式繼承

原理:
原型鏈的查找
現(xiàn)在我們有一個構(gòu)造函數(shù)

function Init(){
    this.name = "init1";
}
Init.prototype.a = function(){
    console.log("這里是init的a方法");
}

如果我們想要繼承這個構(gòu)造函數(shù)Init的屬性,同時不能使用拷貝繼承妥粟,那么我們可以使用下面這種方法:
首先創(chuàng)建好這個init2

function Init2(){
    //這里同樣需要修改init2的this指向來繼承init的屬性
    Init.call(this);
}

我們需要創(chuàng)建一個空的函數(shù)

function F(){};

然后修改這個函數(shù)的原型

F.prototyep = Init.prototype;

然后使用new生成這個F的實例化對象

var objF = new F();

最后审丘,我們把這個實例化對象賦值給Init2prototype,并且手動修正constructor

Init2.prototype = objF;
Init2.constructor = Init2;
//實例化對象勾给,調(diào)用
Init2.prototype.b = function () {
    console.log("this is Init2.b");
};
var in2 = new Init2();
var in1 = new Init();
in2.a();
in2.b();
in1.b();        //這個會報錯

原理:
使用一個空的構(gòu)造函數(shù)作為橋梁滩报,然后把空的構(gòu)造函數(shù)的實例化對象賦值給需要繼承的構(gòu)造函數(shù)锅知,這樣,當(dāng)調(diào)用in2的a方法的時候脓钾,由于它本身沒有a方法售睹,通過__proto__去向上找他的構(gòu)造函數(shù)init2.prototype,但是Init2.prototype = objF這個實例化對象可训,那么會通過__proto__去向上找他的構(gòu)造函數(shù)FFprototype,但是F.prototype = init.prototype,這樣就通過原型鏈找到了a方法昌妹。

in2.a -> objF ->objF.__protot__ -> F ->F.prototype ->init.prototype

這個時候,init.prototype和F.prototype指向同一個對象沉噩,init2的prototype和objF指向同一個對象捺宗。

6.3 對象繼承

如果現(xiàn)在有一個對象obj1

var obj1 = {
    "name":"momo",
    "age":20,
    "say":function(){
        alert(1);
    }
};

利用類式繼承的原理,我們可以完美繼承這個對象川蒙,方法如下

var obj2 = {};
function F(){};
F.prototype = obj1;
var objF = new F;
obj2 = objF;

這個時候調(diào)用obj2.say方法蚜厉,可以alert(1);
給obj2添加新得key也不會影響到obj1
通過原型鏈的查找順序為:

obj2.a -> objF ->objF.__proto__ ->F ->F.prototype ->obj1

7 toString

作用:把數(shù)據(jù)轉(zhuǎn)成字符串。
每個數(shù)據(jù)類型自身都有toString方法
只要使用alert彈出引用類型的數(shù)據(jù)畜眨,那么就會調(diào)用toString方法昼牛。

Array.prototype.toString = function () {
    return 'aaa';
};
var arr = [1,2,3];
alert(arr);

但是彈出基本類型就不會調(diào)用toString方法

如果為數(shù)字類型,那么在toString的括號中寫進(jìn)制康聂,那么就會轉(zhuǎn)成對應(yīng)的進(jìn)制結(jié)果贰健。(轉(zhuǎn)基數(shù))

var num = 255;
var num2 = "11001000";   //200

console.log(num.toString(2));       //11111111
console.log(parseInt(num2,2));      //200

7.1 判斷數(shù)據(jù)類型

1.typeof

typeof 數(shù)據(jù)

缺點(diǎn)是沒辦法判斷數(shù)組的數(shù)據(jù)類型

2.instanceof

數(shù)據(jù) instanceof 數(shù)據(jù)類型(構(gòu)造函數(shù))

3.constructor

數(shù)據(jù).constructor

返回一個數(shù)據(jù)的構(gòu)造函數(shù),但是這個對于判斷ifream中的內(nèi)容有問題

4.Object.prototype.toString.call(數(shù)據(jù))

Object.prototype.toString.call(數(shù)據(jù))

這個方法會返回一個[object 數(shù)據(jù)構(gòu)造函數(shù)]恬汁;

精確返回伶椿,即使在ifream中的數(shù)據(jù)也沒有問題

8.forEach

將一個類數(shù)組轉(zhuǎn)換為數(shù)組

var boxs = document.querySelectorAll("div");
var boxarr = Array.prototype.slice.call(boxs);
//這樣就可以使用forEach來循環(huán)類數(shù)組啦
boxarr.forEach(function(elem,i){
    elem.onclick = function(){
        alert(i);
    }
});

問題:Object.prototype.toString和Array.prototype.slice這兩個都是通過改變this的指向來實現(xiàn)效果,那么Array.prototype.slice的this原來是誰氓侧? 是它的實例化對象脊另? 還是window?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末约巷,一起剝皮案震驚了整個濱河市偎痛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌独郎,老刑警劉巖踩麦,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異氓癌,居然都是意外死亡谓谦,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門贪婉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來茁计,“玉大人,你說我怎么就攤上這事⌒茄梗” “怎么了践剂?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長娜膘。 經(jīng)常有香客問我逊脯,道長,這世上最難降的妖魔是什么竣贪? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任军洼,我火速辦了婚禮,結(jié)果婚禮上演怎,老公的妹妹穿的比我還像新娘匕争。我一直安慰自己,他們只是感情好爷耀,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布甘桑。 她就那樣靜靜地躺著,像睡著了一般歹叮。 火紅的嫁衣襯著肌膚如雪跑杭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天咆耿,我揣著相機(jī)與錄音德谅,去河邊找鬼。 笑死萨螺,一個胖子當(dāng)著我的面吹牛窄做,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播慰技,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼浸策,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了惹盼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤惫确,失蹤者是張志新(化名)和其女友劉穎手报,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體改化,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡掩蛤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了陈肛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片揍鸟。...
    茶點(diǎn)故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖句旱,靈堂內(nèi)的尸體忽然破棺而出阳藻,到底是詐尸還是另有隱情晰奖,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布腥泥,位于F島的核電站匾南,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏蛔外。R本人自食惡果不足惜蛆楞,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望夹厌。 院中可真熱鬧豹爹,春花似錦、人聲如沸矛纹。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽崖技。三九已至逻住,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間迎献,已是汗流浹背瞎访。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吁恍,地道東北人扒秸。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像冀瓦,于是被迫代替她去往敵國和親伴奥。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評論 2 348