javascript
JavaScript原型链(重要)
1. 構(gòu)造函數(shù)與原型
先了解一個(gè)概念:
類就是對(duì)象的模板,對(duì)象就是類的實(shí)例。
在構(gòu)造函數(shù)內(nèi)部的this指向它的實(shí)例對(duì)象。
2. new關(guān)鍵字
這個(gè)也是面試常考的知識(shí)點(diǎn)
在實(shí)例化構(gòu)造函數(shù)時(shí),做了什么?或者說(shuō)在JavaScript中new
創(chuàng)建空對(duì)象 var zs = { }
將構(gòu)造函數(shù)內(nèi)部的this指向空對(duì)象 this -> zs
把屬性和方法掛載到實(shí)例對(duì)象上。 zs.name zs.age zs.sing()
隱式返回新對(duì)象。
3. 實(shí)例成員與靜態(tài)成員
- 實(shí)例成員:在構(gòu)造函數(shù)內(nèi)部創(chuàng)建的對(duì)象成員稱為實(shí)例成員,只能由實(shí)例化的對(duì)象來(lái)訪問(wèn)。
- 靜態(tài)成員:在構(gòu)造函數(shù)本身上添加的成員稱為靜態(tài)成員,只能由構(gòu)造函數(shù)本身來(lái)訪問(wèn)。
4. 構(gòu)造函數(shù)與靜態(tài)成員
同一個(gè)函數(shù),會(huì)在內(nèi)存中保存多份,會(huì)造成內(nèi)存的浪費(fèi)。
<script>function Cup(color, size) {this.color = colorthis.size = sizethis.save = function () {console.log("儲(chǔ)水");}}var mycup1 = new Cup("紫色", "3400ml")var mycup2 = new Cup("綠色", "400ml")console.log(mycup1);console.log(mycup2);mycup1.save()mycup2.save()引用數(shù)據(jù)類型,比較的是內(nèi)存中的地址console.log(mycup1.save == mycup2.save);輸出false地址不同,造成浪費(fèi) </script>引用性數(shù)據(jù)類型比較的是地址
5. 原型對(duì)象Prototype/[__proto__]
是構(gòu)造函數(shù)的屬性;
是Object類
構(gòu)造函數(shù)的原型protoeype,作用是實(shí)現(xiàn)對(duì)象和屬性共享,解決內(nèi)存浪費(fèi)問(wèn)題。
每個(gè)一構(gòu)造函數(shù)都有一個(gè)protoeype屬性指向一個(gè)對(duì)象,這個(gè)prototype就是一個(gè)對(duì)象,這個(gè)對(duì)象的所有屬性和方法,都會(huì)被構(gòu)造函數(shù)所有。
一般情況下,我們公共屬性放在構(gòu)造函數(shù)里面,公共的方法我們放到原型對(duì)象身上。
原型對(duì)象里面的this指向的就是這個(gè)實(shí)例對(duì)象
作用:可以通過(guò)原型對(duì)象,對(duì)原來(lái)的內(nèi)置對(duì)象進(jìn)行拓展自定義的方法。
function Cup(color, size) {this.color = colorthis.size = sizeCup.prototype.save = function () {console.log("儲(chǔ)水");}Cup.prototype.fill = function () {console.log("儲(chǔ)水");}}6. __proto__
對(duì)象能夠訪問(wèn)原型對(duì)象中的方法:
原因:對(duì)象的_ _ proto_ _ 屬性指向構(gòu)造函數(shù)的prototype/原型對(duì)象
名稱:對(duì)象原型
- __proto__對(duì)象原型和原型對(duì)象prototype是等價(jià)的
- __proto__對(duì)象原型的意義就在于為對(duì)象的查找機(jī)制提供一個(gè)方向,或者說(shuō)是一條路線,但是它是一個(gè)非標(biāo)準(zhǔn)屬性,因此實(shí)際開發(fā)中,不可以使用這個(gè)屬性,他只是內(nèi)部指向原型對(duì)象prototype.
非標(biāo)準(zhǔn):
不能使用,只能直接看他指向的結(jié)果,不能設(shè)置,只能直接訪問(wèn)
7. constructor屬性
對(duì)象原型(__proto__)和構(gòu)造函數(shù)(prototype)原型對(duì)象里面都有一個(gè)屬性constructor屬性,constructor我們稱為構(gòu)造函數(shù),因此它指回構(gòu)造函數(shù)本身。
- 作用:主要用于記錄該對(duì)象引用哪個(gè)構(gòu)造函數(shù),它可以讓原型對(duì)象重新指向原來(lái)的構(gòu)造函數(shù)。
constructor屬性在那里可以訪問(wèn):
__proto__有constructor屬性
原型對(duì)象/prototype有constructor屬性
我們稱constructor為構(gòu)造函數(shù)。
使用:當(dāng)以對(duì)象的形式修改原型對(duì)象的內(nèi)容時(shí),會(huì)發(fā)現(xiàn)修改后的屬性把原來(lái)的屬性覆蓋掉了,這時(shí)候就需要重新設(shè)置一下constructor屬性,并指揮回原來(lái)的構(gòu)造函數(shù)。
function Cup(color, size) {this.color = colorthis.size = size}Cup.prototype = {constructor: Cup,save: function () {console.log("儲(chǔ)水");},warn: function () {console.log("保溫");}}(以對(duì)象的形式,修改了原型對(duì)象中的內(nèi)容,這樣修改后的原型對(duì)象constructor就不再指向當(dāng)前構(gòu)造函數(shù)了。此時(shí),我們可以在修改后的原型對(duì)象中,添加一個(gè)constructor指向原來(lái)的構(gòu)造函數(shù))
8.原型鏈
JavaScript對(duì)象,都有__proto__屬性,指向原型對(duì)象。
(mycup,Cup,Object,null)
- 作用:js中在查找對(duì)象和屬性的方式時(shí),遵循的一條鏈?zhǔn)揭?guī)則。
- 當(dāng)訪問(wèn)一個(gè)對(duì)象的屬性(包括方法)時(shí),首先找到這個(gè)對(duì)象自身有沒(méi)有該屬性
- 如果沒(méi)有就查找它的原型(也就是__proto__指向的prototype原型對(duì)象)
- 如果還沒(méi)有就查找原型對(duì)象的原型(Object原型對(duì)象)
- 以此類推一直找到Object為止(null)
- __proto__對(duì)象原型的意義在于為對(duì)象成員查找機(jī)制提供了一種方向,或者說(shuō)一條路線。
如果原型鏈找不到屬性,undefined。如果找不到方法,會(huì)報(bào)錯(cuò)。
-
關(guān)系:instance.constructor.prototype == instance.__proto__
-
特點(diǎn):JavaScript對(duì)象是通過(guò)引用來(lái)傳遞的,我們創(chuàng)建的每個(gè)新對(duì)象實(shí)體中并沒(méi)有一份屬于自己的原型副本。當(dāng)我們修改原型時(shí),與之相關(guān)的對(duì)象也會(huì)繼承這一改變。
小例子:
function Cup(color, size) {this.color = colorthis.size = size}Cup.prototype = {constructor: Cup,save: function () {console.log("儲(chǔ)水");},warn: function () {console.log("保溫");}}var mycup = new Cup("粉色", "1500ml")console.log(mycup);console.log(mycup.__proto__ == Cup.prototype);console.log(mycup.__proto__.constructor); //指向當(dāng)前的構(gòu)造函數(shù)console.log(Cup.prototype.constructor); //指向當(dāng)前的構(gòu)造函數(shù)//驗(yàn)證原型鏈console.log(mycup.__proto__ == Cup.prototype);console.log(Cup.prototype.__proto__ == Object.prototype);console.log(Object.prototype.__proto__ == null);var arr = [1, 2, 3]var arr1 = new Array(1, 2, 3)console.log(arr, arr1);arr1.push(4)Array.prototype.sum = function () {var total = 0;for (var i = 0; i < this.length; i++) {total += this[i];}return total}console.log(arr.sum());console.log(arr1.sum());9.繼承
JavaScript如何實(shí)現(xiàn)繼承
- 構(gòu)造繼承
- 原型繼承
- 實(shí)例繼承
- 拷貝繼承
- 原型prototype機(jī)制或apply和call方法去實(shí)現(xiàn)較簡(jiǎn)單,建議使用構(gòu)造函數(shù)與原型混合方式
ES6:利用extends實(shí)現(xiàn)繼承
組合繼承:構(gòu)造函數(shù)+原型對(duì)象
es5繼承:構(gòu)造函數(shù)+原型對(duì)象
//es5繼承:構(gòu)造函數(shù) + 原型對(duì)象//1. 利用構(gòu)造函數(shù)繼承屬性function Father(name, age) {this.name = namethis.age = age}Father.prototype.work = function () {console.log("工作");}function Son(name, age, gender) {Father.call(this, name, age);this.gender = gender;}Son.prototype = new Father() //子構(gòu)造函數(shù)的peototype = new 父構(gòu)造函數(shù)Son.prototype.constructor = Son; // 子構(gòu)造函數(shù)的constructor手動(dòng)設(shè)置為sonSon.prototype.study = function () {console.log("學(xué)習(xí)");}var son = new Son('xh', 6, "男")console.log(son);核心原理:
- 將子類所共享的方法提取出來(lái),讓子類的prototype原型對(duì)象 = new 父類()
- 本質(zhì):子類原型對(duì)象等于是實(shí)例化父類,因?yàn)楦割悓?shí)例化后另外開辟空間,就不會(huì)影響原來(lái)的父類
- 將子類的constructoe重新指向子類的構(gòu)造函數(shù)
利用原型對(duì)象繼承方法
es6:繼承: extend
//es6: 類 extendsclass Father1 {constructor(name, age) {this.name = namethis.age = age}work() {console.log("父親工作");}}class Son1 extends Father1 {constructor(name, age, gender) {super(name, age)this.gender = gender}study() {console.log("子學(xué)習(xí)");}}var son1 = new Son1("小米", 20, "男")console.log(son1);es6繼承的關(guān)鍵:extend , super
10.對(duì)象的特性
- 封裝
將對(duì)象所有的組成部分組合起來(lái),盡可能的隱藏對(duì)象的部分細(xì)節(jié),使其受到保護(hù),只提供有限的接口與外部發(fā)生聯(lián)系。
- 優(yōu)點(diǎn):
- 安全,使用時(shí)無(wú)法看到具體的細(xì)節(jié),只需要直接調(diào)用
- 便于修改操作
- 繼承
將對(duì)象擁有另外一個(gè)對(duì)象的屬性和方法。
父類(基類):被繼承的對(duì)象。
子類:繼承的對(duì)象
- 優(yōu)點(diǎn):
- 提高代碼重用性,提高代碼的邏輯性和可維護(hù)性。
使用es5和es6實(shí)現(xiàn)類的封裝
上面這兩種完全等同,但es6的更簡(jiǎn)單,封裝更容易
11.函數(shù)
函數(shù)的三種定義方式
由于聲明函數(shù)方式的不同以及預(yù)解析的因素,導(dǎo)致1,2兩種方式略微不同。1,這種定義方式,把函數(shù)調(diào)用提前是完全沒(méi)有問(wèn)題的,但2,這種方式就會(huì)報(bào)錯(cuò)。(預(yù)解析知識(shí)點(diǎn))
這種方式也是可以傳參的,但由于寫法復(fù)雜,用的并不多。
函數(shù)的調(diào)用
改變this指向的三種方式
call方法
- thisAry:當(dāng)前調(diào)用函數(shù)this的指向?qū)ο?/li>
- arg1,arg2:傳遞的其他參數(shù)
返回值就是函數(shù)的返回值
var obj = { name: "zs", age: 20 }function fn(num) {console.log(1); 20console.log(this); 21console.log(num); 22}fn(0); 25fn.call(obj, 'call') 28很明顯可以看到又調(diào)用了 一次函數(shù)。而且this指向也變成了obj,不再是window了
apply方法
- thisAry:在fun函數(shù)運(yùn)行時(shí)指定的this值
- arg1,arg2 :傳遞的其他參數(shù)
返回值就是函數(shù)的返回值
var obj = { name: "zs", age: 20 }function fn(num) {console.log(1); 20console.log(this); 21console.log(num); 22}fn(0); 25fn.apply(obj, ['apply']) 31和call方法一樣,也會(huì)調(diào)用函數(shù)
也可以不改變參數(shù)只傳值,不常用。
fn.apply(null, ['apply'])bind方法
用到比較多
- thisArg:在fun函數(shù)運(yùn)行時(shí)指向的this值
- arg1,arg2:傳遞的參數(shù)
返回由原來(lái)函數(shù)改變this之后的新函數(shù)
var obj = { name: "zs", age: 20 }function fn(num) {console.log(1); 20console.log(this); 21console.log(num); 22}fn(0); 25var f = fn.bind(obj, "bind") 33fn() 34總結(jié)
| call | 是 | 是 | 就是函數(shù)返回值 | 用來(lái)繼承 |
| apply | 是 | 是 | 就是函數(shù)返回值 | 數(shù)組相關(guān) |
| bind | 是 | 否 | 返回由原函數(shù)改變this之后的新函數(shù) | 不希望函數(shù)立即執(zhí)行(比如定時(shí)器) |
原型,構(gòu)造函數(shù),實(shí)例,以及原型鏈
原型,構(gòu)造函數(shù),實(shí)例三者之間的關(guān)系
總結(jié)
以上是生活随笔為你收集整理的JavaScript原型链(重要)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【MarkDown语法以及软件的安装】
- 下一篇: css 灰度_如何在滚动上建立灰度到色彩