JS 學(xué)習(xí)筆記 | 構(gòu)造函數(shù)和原型

1.構(gòu)造函數(shù)和原型

1.1 對(duì)象的三種創(chuàng)建方式--復(fù)習(xí)

  1. 字面量方式

    var obj = {};
    
  2. new關(guān)鍵字

    var obj = new Object();
    
  3. 構(gòu)造函數(shù)方式

    function Person(name,age){
      this.name = name;
      this.age = age;
    }
    var obj = new Person('zs',12);
    

1.2 靜態(tài)成員和實(shí)例成員

1.2.1 實(shí)例成員

實(shí)例成員就是構(gòu)造函數(shù)內(nèi)部通過 this 添加的成員 如下列代碼中 uname age sing就是實(shí)例成員扣汪,實(shí)例成員只能通過實(shí)例化的對(duì)象來訪問鞠抑。

function Star(uname, age) {
    this.uname = uname;
    this.age = age;
    this.sing = function () {
        console.log('我會(huì)唱歌');
    }
}
var ldh = new Star('劉德華', 18);
console.log(ldh.uname); // 實(shí)例成員只能通過實(shí)例化的對(duì)象來訪問

1.2.2 靜態(tài)成員

靜態(tài)成員 在構(gòu)造函數(shù)本身上添加的成員 如下列代碼中 sex 就是靜態(tài)成員,靜態(tài)成員只能通過構(gòu)造函數(shù)來訪問寻馏。

function Star(uname, age) {
    this.uname = uname;
    this.age = age;
    this.sing = function () {
        console.log('我會(huì)唱歌');
    }
}
Star.sex = '男';
var ldh = new Star('劉德華', 18);
console.log(Star.sex);  // 靜態(tài)成員只能通過構(gòu)造函數(shù)來訪問

1.3 構(gòu)造函數(shù)的問題

構(gòu)造函數(shù)方法很好用定铜,但是存在浪費(fèi)內(nèi)存的問題衙解。

在這里插入圖片描述

1.4 構(gòu)造函數(shù)原型 prototype

構(gòu)造函數(shù)通過原型分配的函數(shù)是所有對(duì)象所共享的隘膘。

JavaScript 規(guī)定屋确,每一個(gè)構(gòu)造函數(shù)都有一個(gè) prototype 屬性舌胶,指向另一個(gè)對(duì)象。注意這個(gè)prototype 就是一個(gè)對(duì)象答倡,這個(gè)對(duì)象的所有屬性和方法轰传,都會(huì)被構(gòu)造函數(shù)所擁有。

我們可以把那些不變的方法瘪撇,直接定義在 prototype 對(duì)象上获茬,這樣所有對(duì)象的實(shí)例就可以共享這些方法。

例如:

function Star(uname, age) {
    this.uname = uname;
    this.age = age;
}
Star.prototype.sing = function() {
    console.log(this.uname + "會(huì)唱歌");
}

var ldh = new Star("劉德華", 18);
var zxy = new Star("張學(xué)友", 19);
console.log(ldh.sing === zxy.sing); // true

運(yùn)行結(jié)果:


在這里插入圖片描述

1.5.對(duì)象原型

每個(gè)對(duì)象都會(huì)有一個(gè) __proto__ 屬性指向構(gòu)造函數(shù)的 prototype 原型對(duì)象倔既,之所以對(duì)象可以使用構(gòu)造函數(shù) prototype 原型對(duì)象的屬性和方法恕曲,就是因?yàn)橛?__proto__ 原型的存在。

在這里插入圖片描述

function Star(uname, age) {
    this.uname = uname;
    this.age = age;
}
Star.prototype.sing = function() {
    return this.uname + "會(huì)唱歌";
}

var ldh = new Star("劉德華", 18);
console.log(ldh.__proto__ === Star.prototype);  // true

通過上面的代碼可以得知渤涌,ldh.__proto__ 指向了 Star.prototype佩谣,所以它們是等價(jià)的

ldh.sing();

方法的查找規(guī)則:首先先看 ldh 對(duì)象身上是否有 sing() 方法,如果有就執(zhí)行對(duì)象身上的方法实蓬,如果沒有則通過 __proto__ 在構(gòu)造函數(shù)原型對(duì)象上查找 sing() 方法茸俭。

注意__proto__ 對(duì)象原型的意義就在于為對(duì)象的查找機(jī)制提供一個(gè)方向,或者說一條路線安皱,但是它是一個(gè)非標(biāo)準(zhǔn)屬性调鬓,因此實(shí)際開發(fā)中,不可以使用這個(gè)屬性酌伊,它只是內(nèi)部指向原型對(duì)象 prototype腾窝。

1.6 constructor 構(gòu)造函數(shù)

對(duì)象原型(__proto__) 和構(gòu)造函數(shù)原型對(duì)象(prototype)里面都有一個(gè) constructor 屬性,constructor 被稱為構(gòu)造函數(shù)居砖,因?yàn)樗赶驑?gòu)造函數(shù)本身燕锥。

constructor 主要用于記錄該對(duì)象引用于哪個(gè)構(gòu)造函數(shù),它可以讓原型對(duì)象重新指向原來的構(gòu)造函數(shù)悯蝉。

一般情況下归形,對(duì)象的方法都在構(gòu)造函數(shù)的原型中設(shè)置,如果有多個(gè)對(duì)象的方法鼻由,我們可以給原型采取對(duì)象形式賦值暇榴,但是這樣會(huì)覆蓋構(gòu)造函數(shù)原型對(duì)象原來的內(nèi)容厚棵,這樣修改后的原型的 constructor 就不再指向當(dāng)前構(gòu)造函數(shù)了。此時(shí)蔼紧,我們可以在修改后的原型中婆硬,添加一個(gè) constructor 指向原來的構(gòu)造函數(shù)。

如果我們修改了原來的原型奸例,給原型賦值的是一個(gè)對(duì)象彬犯,則必須手動(dòng)的利用 constructor 指回原來的構(gòu)造函數(shù)如:

function Star(uname, age) {
    this.uname = uname;
    this.age = age;
}

Star.prototype = {
    // 指回原來的構(gòu)造函數(shù)
    constructor: Star,
    sing: function() {
        console.log("我會(huì)唱歌");
    },
    movie: function() {
        console.log("我會(huì)演電影");
    }
}

console.log(Star.prototype.constructor);
console.log(ldh.__proto__.constructor);

1.7 原型鏈

每個(gè)對(duì)象都有一個(gè) __proto__ 屬性,指向構(gòu)造函數(shù)的原型查吊,構(gòu)造函數(shù)的原型也是一個(gè)對(duì)象谐区,也有 __proto__ 屬性,這樣一層層往上找就形成了原型鏈逻卖。

在這里插入圖片描述

1.8 原型鏈和成員的查找機(jī)制

任何對(duì)象都有原型對(duì)象宋列,也就是 prototype 屬性,任何原型對(duì)象都是對(duì)象评也,所以都有 __proto__ 屬性炼杖,這樣就形成了一條鏈,我們也稱為原型鏈盗迟。

  • 查找一個(gè)對(duì)象的方法(包括屬性)時(shí)坤邪,首先查看這個(gè)對(duì)象自身包不包含這個(gè)方法。
  • 如果沒有就查找它的原型罚缕,也就是 __proto__ 指向的 prototype 原型艇纺。
  • 如果還沒有就查找原型對(duì)象的原型(Object 的原型對(duì)象)
  • 直到查找到 null 為止。

總結(jié)__proto__ 的意義在于給對(duì)象查找屬性或方法提供了一個(gè)方向怕磨。

1.9 原型對(duì)象的 this 指向

構(gòu)造函數(shù)中的 this 和原型對(duì)象的 this喂饥,都指向我們 new 出來的實(shí)例對(duì)象消约。

function Star(uname, age) {
    this.uname = uname;
    this.age = age;
}
var that;
Star.prototype.sing = function() {
    console.log('我會(huì)唱歌');
    that = this;
}
var ldh = new Star('劉德華', 18);
ldh.sing();
// 1. 在構(gòu)造函數(shù)中,里面this指向的是對(duì)象實(shí)例 ldh
console.log(that === ldh);//true
// 2.原型對(duì)象函數(shù)里面的this 指向的是 實(shí)例對(duì)象 ldh

執(zhí)行結(jié)果:


在這里插入圖片描述

1.10 通過原型為數(shù)組擴(kuò)展內(nèi)置方法

可以通過原型對(duì)象肠鲫,對(duì)原來的內(nèi)置對(duì)象進(jìn)行擴(kuò)展自定義的方法。比如給數(shù)組添加自定義求偶數(shù)和的功能或粮。

// 原型對(duì)象的應(yīng)用导饲,擴(kuò)展內(nèi)置對(duì)象方法
 console.log(Array.prototype);
 Array.prototype.sum = function() {
     var sum = 0;
     for (var i = 0; i < this.length; i++) {
         sum += this[i];
     }
     return sum;
 }

 var arr = [1,2,3];
 console.log(arr.sum());

2.繼承

ES6 之前并沒有給我們提供 extends 繼承。我們可以通過構(gòu)造函數(shù) + 原型對(duì)象模擬實(shí)現(xiàn)繼承氯材,這種方式也被稱為 組合繼承渣锦。

2.1 call()

該方法可以調(diào)用函數(shù),并且修改函數(shù)運(yùn)行時(shí)的 this 指向

語法:

func.call(thisArg, arg1, arg2, ...);
  • func:需要調(diào)用的函數(shù)名
  • thisArg:當(dāng)前調(diào)用函數(shù) this 的指向?qū)ο?/li>
  • arg1氢哮、arg2:傳遞的參數(shù)
function func() {
    console.log(this);
    console.log("我喜歡喝手磨咖啡");
}
var lyman = {name: "lyman"};
func.call(lyman);   // 如果不傳入?yún)?shù)袋毙,默認(rèn)使用 window

2.2 子構(gòu)造函數(shù)繼承父構(gòu)造函數(shù)中的屬性

核心原理:通過 call() 把父類型的 this 指向子類型的 this,這樣就可以實(shí)現(xiàn)子類型繼承父類型屬性冗尤。

例如:

// 1.父構(gòu)造函數(shù)
function Father(uname, age) {
    this.uname = uname;
    this.age = age;
}

// 2.子構(gòu)造函數(shù)
function Son(uname, age) {
    Father.call(this, uname, age);
}

var son = new Son("lyman", 22);
console.log(son);

2.3 借用原型對(duì)象繼承方法

  • 先定義一個(gè)父構(gòu)造函數(shù)
  • 再定義一個(gè)子構(gòu)造函數(shù)
  • 子構(gòu)造函數(shù)繼承父構(gòu)造函數(shù)的屬性和方法
function Father(uname, age) {
    this.uname = uname;
    this.age = age;
}

Father.prototype.money = function() {
    console.log(100000);
}

// 2.子構(gòu)造函數(shù)
function Son(uname, age, score) {
    Father.call(this, uname, age);
    this.score = score;
}

// 這樣直接賦值會(huì)有問題听盖,如果直接修改了子原型對(duì)象胀溺,父原型對(duì)象也會(huì)被改變
// Son.prototype = Father.prototype;    
Son.prototype = new Father();
// 如果利用對(duì)象的形式修改了原型對(duì)象,別忘了利用 constructor 指回原來的構(gòu)造函數(shù)
Son.prototype.constructor = Son;

Son.prototype.exam = function() {
    console.log("孩子要考試");
}

var son = new Son("lyman", 22, 100);
console.log(son);
son.money();
console.log(Father.prototype);
console.log(Son.prototype.constructor);

3.ES5 新增方法

3.1 數(shù)組方法

3.1.1 forEach

數(shù)組方法皆看,遍歷數(shù)組
語法:

arr.forEach(function(value, index, array) {
      //參數(shù)一是:數(shù)組元素
      //參數(shù)二是:數(shù)組元素的索引
      //參數(shù)三是:當(dāng)前的數(shù)組
})
//相當(dāng)于數(shù)組遍歷的 for循環(huán) 沒有返回值

例如:

// forEach 遍歷數(shù)組
var arr = [1,2,3];
arr.forEach(function(value, index, arr) {
    console.log("每個(gè)數(shù)組元素:" + value);
    console.log("每個(gè)數(shù)組元素的索引:" + index);
    console.log("數(shù)組本身:" + arr);
})

3.1.2 filter

創(chuàng)建一個(gè)新數(shù)組仓坞,新數(shù)組中的元素是通過檢查指定數(shù)組中符合條件的所有元素,主要用于篩選數(shù)組腰吟。

語法:

arr.filter(function(currentValue, index, arr) {
    //參數(shù)一是:數(shù)組元素
    //參數(shù)二是:數(shù)組元素的索引
    //參數(shù)三是:當(dāng)前的數(shù)組
})

例如:

// filter 篩選數(shù)組
var arr = [12, 66, 88];
var res = arr.filter(function(value, index, arr) {
    return value >= 20;
})
res.forEach(function(value, index, arr) {
    console.log(value);
}) 

3.1.3 some

該方法用于檢測數(shù)組中是否有滿足指定條件的元素无埃,該方法的返回值是 boolean 類型,如果查找到滿足條件的元素返回 true毛雇,否則返回 false嫉称。找到第一個(gè)滿足條件的元素就會(huì)終止循環(huán),不再繼續(xù)查找禾乘。

語法:

arr.some(function(currentValue, index, arr) {
    //參數(shù)一是:數(shù)組元素
    //參數(shù)二是:數(shù)組元素的索引
    //參數(shù)三是:當(dāng)前的數(shù)組
})

例如:

var arr = [10, 30, 4];
var res = arr.some(function(value, index, arr) {
    return value > 20;
})
console.log(res);

3.2 字符串方法

3.2.1 trim

該方法會(huì)從一個(gè)字符串的兩端刪除空白字符澎埠,刪除完成后返回一個(gè)新的字符串,并不會(huì)影響原字符串始藕。

語法:

str.trim();

例如:

var str = "     ly   man   ";
console.log(str.trim());
console.log(str);

3.3 對(duì)象方法

3.3.1 Object.keys

該方法用于獲取對(duì)象自身的所有屬性

例如:

Object.keys(對(duì)象名);

返回一個(gè)由屬性名組成的數(shù)組蒲稳。

例如:

var phone = {
    id: 1,
    pname: "小米",
    price: 1999,
    num: 2000
}

var arr = Object.keys(phone);
console.log(arr);

3.3.2 Object.defineProperty

該方法用于定義新屬性或修改原有屬性

語法:

Object.defineProperty(obj, prop, descriptor);
  • obj:目標(biāo)對(duì)象
  • prop:需定義或修改的屬性的名字(必須是字符串)
  • descriptor:目標(biāo)屬性所擁有的特性(必須是對(duì)象)

例如:

var phone = {
    id: 1,
    pname: "小米",
    price: 1999
}
Object.defineProperty(phone, "num", {
    value: 1000
});
console.log(phone);

除此之外還可以設(shè)置對(duì)象的屬性是否可寫、可枚舉伍派、可修改江耀。

Object.defineProperty(對(duì)象,修改或新增的屬性名诉植,{
    value:修改或新增的屬性的值,
    writable:true/false,//如果值為false 不允許修改這個(gè)屬性值
    enumerable: false,//enumerable 如果值為false 則不允許遍歷
    configurable: false  //configurable 如果為false 則不允許刪除這個(gè)屬性 屬性是否可以被刪除或是否可以再次修改特性
})  
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末祥国,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子晾腔,更是在濱河造成了極大的恐慌舌稀,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灼擂,死亡現(xiàn)場離奇詭異壁查,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)剔应,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門睡腿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人峻贮,你說我怎么就攤上這事席怪。” “怎么了纤控?”我有些...
    開封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵挂捻,是天一觀的道長。 經(jīng)常有香客問我船万,道長刻撒,這世上最難降的妖魔是什么惜辑? 我笑而不...
    開封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮疫赎,結(jié)果婚禮上盛撑,老公的妹妹穿的比我還像新娘。我一直安慰自己捧搞,他們只是感情好抵卫,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著胎撇,像睡著了一般介粘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上晚树,一...
    開封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天姻采,我揣著相機(jī)與錄音,去河邊找鬼爵憎。 笑死慨亲,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的宝鼓。 我是一名探鬼主播刑棵,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼愚铡!你這毒婦竟也來了蛉签?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤沥寥,失蹤者是張志新(化名)和其女友劉穎碍舍,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體邑雅,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡片橡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蒂阱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锻全。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡狂塘,死狀恐怖录煤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情荞胡,我是刑警寧澤妈踊,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站泪漂,受9級(jí)特大地震影響廊营,放射性物質(zhì)發(fā)生泄漏歪泳。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一露筒、第九天 我趴在偏房一處隱蔽的房頂上張望呐伞。 院中可真熱鬧,春花似錦慎式、人聲如沸伶氢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽癣防。三九已至,卻和暖如春掌眠,著一層夾襖步出監(jiān)牢的瞬間蕾盯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來泰國打工蓝丙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留级遭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓渺尘,卻偏偏與公主長得像装畅,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子沧烈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355