亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

深入淺析js原型鏈和vue構造函數

2019-11-19 12:38:12
字體:
來源:轉載
供稿:網友

一、什么是原型鏈?

簡單回顧下構造函數,原型和實例的關系:

     每個構造函數(constructor)都有一個原型對象(prototype),原型對象都包含一個指向構造函數的指針,而實例(instance)都包含一個指向原型對象的內部指針.

然鵝,在js對象里有這么一個規則:

  如果試圖引用對象(實例instance)的某個屬性,會首先在對象內部尋找該屬性,直至找不到,然后才在該對象的原型(instance.prototype)里去找這個屬性.

少廢話,先來看個例子:

function Fun1 () {  this.win = "skt" } Fun1.prototype.getVal = function () {  return this.win } function Fun2 () {  this.other_win = "rng" } Fun2.prototype = new Fun1 () Fun2.prototype.getOtherVal = function () {  return this.other_win } let instance = new Fun2() console.log(instance.getVal()) //skt

在上述例子中,有一個很有意思的操作,我們讓原型對象指向了另一個類型的實例,即: constructor1.property = instance2

那么他是怎么找到instance.getVal()的?這中間又發生了什么?

  1).首先會在instance1內部屬性中找一遍;

  2).接著會在instance1.__proto__(constructor1.prototype)中找一遍,而constructor1.prototype 實際上是instance2, 也就是說在instance2中尋找該屬性;

  3).如果instance2中還是沒有,此時程序不會灰心,它會繼續在instance2.__proto__(constructor2.prototype)中尋找...直至Object的原型對象

    搜索軌跡: instance1--> instance2 --> constructor2.prototype…-->Object.prototype

這種搜索的軌跡,形似一條長鏈, 又因prototype在這個游戲規則中充當鏈接的作用,于是我們把這種實例與原型的鏈條稱作 原型鏈

二、prototype 和 __proto__ 都是個啥?

1.prototype是函數才有的屬性

 let fun = function () {} console.log(fun.prototype) // object console.log(fun.__proto__) // function

2.__proto__是對象具有的屬性,但__proto__不是一個規范的屬性,對應的標準屬性是 [[Prototype]]

 let obj = {} console.log(obj.prototype) // underfined console.log(obj.__proto__) // object

我們可以把__proto__理解為構造器的原型,大多數情況下 __proto__ === constructor.prototype      ( Object.create()除外 )

三、new又是個什么鬼?

我們都知道new是一個實例化的過程,那么他是怎么實例化的?下面我們來看一個簡單的例子:

 function Fun() {  this.team = "rng" } let f = new Fun() console.log(f.team) // rng

上述代碼中,我們通過new命令實例化了一個叫Fun的函數并賦值給f,這個新生成的實例對象f從構造函數Fun中得到了team屬性,其實構造函數內部的this,就代表了新生成的實例對象,所以我們打印f.team的值就取到了rng這個值

這又是哪門子原理?答案如下?

1.創建一個空對象,作為將要返回的對象實例。
2.將這個空對象的原型,指向構造函數的prototype屬性。
3.將這個空對象賦值給函數內部的this關鍵字。
4.開始執行構造函數內部的代碼

也就是說,構造函數內部,this指的是一個新生成的空對象,所有針對this的操作,都會發生在這個空對象上。這也是為什么構造函數叫"構造函數"的原因,就是操作一個空對象(即this對象),將其“構造”為所需要的樣子。

如果我不加new呢?

 function Fun() {  this.team = "rng" } let f = Fun() console.log(f) // undefined console.log(team) // rng

我們可以看出上面打印f為undefined,而team卻有值,這又是為什么?

其實在這種情況下,構造函數就變成了普通的函數,而且不會被實例.而此時的this指向了全局,team就變成了全局變量,因此我們取到了值

四、 __proto__指向哪?

  說到__proto__的指向問題,還得取決于該對象創建時的實現方式.

  辣么,到底有那些實現方式?

1.字面量方式

 let obj = {} console.log(obj.__proto__) // object console.log(obj.__proto__ === obj.constructor.prototype) // true 證明用字面量創建的函數,他的__proto__ 等于 該對象構造器的原型

2.構造器方式

 function Func () {} let a = new Func() console.log(a.__proto__) // object console.log(a.__proto__ === a.constructor.prototype) // true

3.Object.create()方式

 let obj1 = {name:"rng"} let obj2 = Object.create(obj1) console.log(obj2.__proto__) //{name: "rng"} console.log(obj2.__proto__ === obj2.constructor.prototype) // false

  注: Object.create(prototype, descriptors) 創建一個具有指定原型且可選擇性地包含指定屬性的對象

五、如何確定原型和實例的關系?

  想要確定原型和實例的關系,坦率的講,有兩種方式:  instance  和  isPrototype()

1.instanceof

  我們用這個操作符來測試實例(instance)與原型鏈中出現過的構造函數,如果出現過則返回true,反之則為false

  來來來,我們來測試一下:

 function Fun1 () {  this.laji = "uzi" } function Fun2 () {  this.strong = "faker" } Fun2.prototype = new Fun1() let fun2 = new Fun2 () console.log(fun2 instanceof Fun1) // true console.log(fun2 instanceof Fun2) // true console.log(fun2 instanceof Object) // true

由于原型鏈的關系,我們可以說fun2是一個對象Object,Fun1或是Fun2中任何一個類型的實例,所以這三個結果都返回了true

2.isPrototype()

  這個方法同樣,只要是原型鏈中出現過的原型,該方法就會返回true,用法如下

 console.log(Fun1.prototype.isPrototypeOf(fun2)) // true console.log(Fun2.prototype.isPrototypeOf(fun2)) // true console.log(Object.prototype.isPrototypeOf(fun2))// true

六、原型鏈的問題

  什么?原型鏈還有問題?買了佛冷,why?

  原因一: 當原型鏈中包含引用類型值的原型時,該引用類型值會被所有實例共享;

  原因二:在創建子類型時,不能向超類型的構造函數中傳遞參數.

七、如何解決原型鏈問題?

1.借用構造函數,也叫經典繼承

  基本思想: 在子類型構造函數的內部調用超類型構造函數

  函數只是在特定環境中執行的代碼的對象,因此通過使用 apply() 和 call() 方法也可以在(將來)新創建的對象上執行構造函數

看例子:

 function Father () {  this.team = ["letme","mlxg"] } function Son () {  Father.call(this) } let son = new Son() son.team.push("uzi") console.log(son.team)  // ["letme", "mlxg", "uzi"] let little_son = new Son()  console.log(little_son.team) // ["letme", "mlxg"]

我們可以看出,借用構造函數一舉解決了原型鏈的兩大問題:

  其一, 保證了原型鏈中引用類型值的獨立,不再被所有實例共享;

  其二, 子類型創建時也能夠向父類型傳遞參數.

但是還還還有一個問題,如果僅僅借用構造函數,那么將無法避免構造函數模式存在的問題:

  方法都在構造函數中定義, 因此函數復用也就不可用了.而且超類型(如Father)中定義的方法,對子類型而言也是不可見的. so,借用構造函數的技術也很少單獨使用.

2.組合繼承

  組合繼承, 有時候也叫做偽經典繼承,指的是將原型鏈和借用構造函數的技術組合到一塊,從而發揮兩者優點的一種繼承模式.

  基本思想: 使用原型鏈實現對原型屬性和方法的繼承,通過借用構造函數來實現對實例屬性的繼承.

  這樣,既通過在原型上定義方法實現了函數復用,又能保證每個實例都有它自己的屬性.

接著看例子:

function Father (team) {  this.team = team  this.people = ["mlxg","letme"] } Father.prototype.sayTeam = function () {  return console.log(this.team) } function Son (team,age) {  this.age = age  Father.call(this,team) } Son.prototype = new Father() Son.prototype.sayAge = function () {  return console.log(this.age) } let son = new Son("faker",8) son.people.push("uzi") console.log(son.people) // ["mlxg", "letme", "uzi"] son.sayAge()    //8 son.sayTeam()    // faker let little_son = new Son("bang",3) console.log(little_son.people) // ["mlxg", "letme"]  little_son.sayAge()    // 3 little_son.sayTeam()   // bang

  我們可以看出,組合繼承既保證了引用類型不再被所有實例所共享,也能夠讓子類型創建時向父類型傳參,同時,原型中的方法又能夠被復用,可以說是避免了原型鏈中的兩大問題以及借用構造函數的缺陷,因此他也是js中最常用的繼承方式,而且

instanceof 和 isPrototypeOf( )也能用于識別基于組合繼承創建的對象.

3.原型繼承

  基本思想: 借助原型可以基于已有的對象創建新對象, 同時還不必因此創建自定義類型

  繩么意思?

  比如我們在fun()函數內部, 先創建一個臨時性的構造函數, 然后將傳入的對象作為這個構造函數的原型,最后返回了這個臨時類型的一個新實例.

 function fun(o){   function F(){}   F.prototype = o;   return new F();  }  let obj = {arr:[11,22]  fun(obj).arr.push(33)  console.log(fun(obj).arr) // [11,22,33]

  在這個例子中,可以作為另一個對象基礎的是obj對象,于是我們把它傳入到fun()函數中,然后該函數就會返回一個新對象. 這個新對象將arr作為原型,因此它的原型中就包含引用類型值屬性. 然后我們向該屬性中又增加了一個元素,所以我們能夠將它打印出來

       *在原型繼承中, 包含引用類型值的屬性始終都會共享相應的值, 就像使用原型模式一樣.

4.寄生式繼承

  基本思想:創建一個僅用于封裝繼承過程的函數,該函數在內部以某種方式來增強對象,最后再像真的是它做了所有工作一樣返回對象

 function fun(o){  function F(){}  F.prototype = o;  return new F(); } let obj = {a:[11,22]} function createAnother(z) {  // 通過調用函數創建一個新對象  var clone = fun(z);  clone.sayHi = function () {   alert("hi");  }  return clone; }    createAnother(obj)

  上面的例子中,我們把obj傳入createAnother()函數中,返回的新對象clone不僅擁有了該屬性,而且還被增強了,擁有了sayHi()方法;

  等一下,這里要注意: 使用寄生式繼承來為對象添加函數, 會由于不能做到函數復用而降低效率;這一點與構造函數模式類似.

5.寄生組合式繼承

  前面講過,組合繼承是 JavaScript 最常用的繼承模式; 不過, 它也有自己的不足. 組合繼承最大的問題就是無論什么情況下,都會調用兩次父類構造函數: 一次是在創建子類型原型的時候, 另一次是在子類型構造函數內部. 寄生組合式繼承就是為了降低調用父類構造函數的開銷而誕生的

  基本思想:不必為了指定子類型的原型而調用超類型的構造函數

 function inheritPrototype(subType, superType) {  var protoType = Object.create(superType.prototype); //創建對象  protoType.constructor = subType;      //增強對象  subType.prototype = protoType;       //指定對象 } function Father(name) {  this.name = name;  this.colors = ["red", "blue", "green"]; } Father.prototype.sayName = function () {  console.log(this.name); } function Son(name, age) {  Father.call(this, name);  this.age = age; } inheritPrototype(Son, Father) Son.prototype.sayAge = function () {  console.log(this.age); } var instance = new Son("uzi", 3); instance.sayName(); //uzi instance.sayAge(); //3

   inheritPrototype函數接收兩個參數:子類型構造函數和超類型構造函數。

    1. 創建超類型原型的副本。

    2. 為創建的副本添加constructor屬性,彌補因重寫原型而失去的默認的constructor屬性

    3. 將新創建的對象(即副本)賦值給子類型的原型

  inheritPrototype的高效率體現在它沒有調用superClass構造函數,因此避免了在subClass.prototype上面創建不必要多余的屬性. 同時,原型鏈還能保持不變,可以說是相當奈斯

  由于寄生組合式繼承,集寄生式繼承和組合繼承的優點于一身,是實現基于類型繼承的最有效方法.

八.vue構造函數

我們在使用的vue的時候,經常會用new操作符去將他實例化,這說明vue也是一個構造函數,那么他是如何被創建的呢?我懷著無比激動的心情clone了vue的源碼,仔細研究了一番

vue源碼地址

我首先找到了src/core/instance/index.js文件,打開一看,驚了

在第八行代碼中,創建了一個Vue的函數,這不就是Vue的構造函數么,而且在12行的警告中我更加肯定了,他說:Vue是一個構造函數,應該使用“new”關鍵字調用
然后他在下面,他分別在

  initMixin()

  stateMixin()

  eventsMixin()

  lifecycleMixin()

  renderMixin()

這五個方法中講Vue作為形參傳入,最后將Vue導出.

那么這五個方法是干什么的呢?我們先來看看initMixin()方法,打開./init.js文件,找到該方法

其他的代碼我們先不管,我們就看該方法的前幾行,他在Vue的原型中注入了_init方法,這個方法有點眼熟,我們好像在哪見過,對,就是剛才的index.js文件中

這個this_init(options)看上去像是一個內部初始化的一個方法,而option應該就是初始化時的一些配置項了,在Vue被實例化的時候,this._init()方法就會執行

接下來,我們來看一下./state.js文件,找到stateMixin方法

總結

以上所述是小編給大家介紹的js原型鏈和vue構造函數,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
中文字幕日韩专区| 亚洲午夜精品久久久久久久久久久久| 国产一级揄自揄精品视频| 国产精品久久久久久久久免费| 中文字幕日韩在线观看| 亚洲美女视频网| 国产亚洲一区二区在线| 中文字幕亚洲天堂| 国产免费观看久久黄| 精品偷拍一区二区三区在线看| 成人福利视频在线观看| 国产精品扒开腿做爽爽爽视频| 亚洲最大福利网站| 大荫蒂欧美视频另类xxxx| 久久影院资源网| 中文字幕日本欧美| 日韩av观看网址| 伊人久久久久久久久久久久久| 国产成人免费av| 夜夜嗨av色综合久久久综合网| 亚洲福利在线视频| 91网站免费观看| 欧美亚洲成人免费| 久久成人人人人精品欧| 久久久久中文字幕2018| 国产91热爆ts人妖在线| 久久久www成人免费精品| 亚洲第一区中文99精品| 亚洲一区免费网站| 亚洲最新av在线网站| 亚洲国产成人久久综合一区| 国产亚洲欧洲黄色| 国产极品jizzhd欧美| 一个色综合导航| 97精品久久久| 亚洲欧美国产高清va在线播| 日韩欧美国产骚| 成人国产精品久久久久久亚洲| 2019中文字幕全在线观看| 国产精品91久久| 欧美性xxxx极品高清hd直播| 国产一区二区免费| 亚洲电影中文字幕| 色樱桃影院亚洲精品影院| 狠狠躁夜夜躁人人爽超碰91| 日韩极品精品视频免费观看| 91免费国产网站| 这里精品视频免费| 日韩中文字幕网| 国产999精品久久久| 欧美激情一区二区三区久久久| 福利视频导航一区| 国产日韩精品在线| 国产精品日韩欧美大师| 欧美电影免费看| 亚洲第一精品久久忘忧草社区| 国产精品视频永久免费播放| 欧美日韩一区二区精品| 亚洲人成自拍网站| 亚洲欧美日韩国产中文| 日韩一中文字幕| 国产精品无码专区在线观看| 精品视频久久久久久| 国产精品电影久久久久电影网| 国产精品wwww| 久久精品视频亚洲| 国产91在线播放九色快色| 91老司机在线| 亚洲最新中文字幕| 在线日韩精品视频| 亚洲男人第一av网站| 欧美插天视频在线播放| 亚洲精品中文字幕有码专区| 国内精品400部情侣激情| 欧美猛交ⅹxxx乱大交视频| 日韩一区视频在线| 欧美成人精品一区二区| 亚洲影影院av| 在线观看日韩视频| 亚洲男人天堂2019| 久久综合伊人77777蜜臀| 国产一区二区欧美日韩| 国产精品国产三级国产aⅴ浪潮| 2019日本中文字幕| 亚洲国产中文字幕久久网| 欧美性受xxxx白人性爽| 久久久精品国产| 91高清视频在线免费观看| 国产精品亚洲综合天堂夜夜| 欧美性受xxx| 尤物tv国产一区| 亚洲乱亚洲乱妇无码| 激情久久av一区av二区av三区| 92福利视频午夜1000合集在线观看| 欧美在线精品免播放器视频| 日韩美女主播视频| 欧美成人精品一区| 97在线视频免费观看| 久久久精品免费视频| 欧美一级免费视频| 精品一区二区三区四区| 日本高清不卡在线| 日韩精品极品在线观看| 欧美成人免费在线视频| 国产成人精品视频在线观看| 日韩在线视频线视频免费网站| 亚洲欧美变态国产另类| 亚洲天堂2020| 2019中文字幕免费视频| 亚洲视频精品在线| 久久91精品国产91久久跳| 亚洲精品免费一区二区三区| 欧美一级淫片aaaaaaa视频| 91情侣偷在线精品国产| 欧美乱大交做爰xxxⅹ性3| 国产精品夜色7777狼人| 98精品国产高清在线xxxx天堂| 国产精品美女免费| 日韩禁在线播放| 精品国产一区二区三区四区在线观看| 亚洲欧美制服丝袜| 欧美高清视频在线播放| 日韩精品www| 欧美老妇交乱视频| 97在线视频免费播放| 午夜精品99久久免费| 亚洲va男人天堂| 日韩国产精品视频| 中文字幕成人在线| 欧美疯狂xxxx大交乱88av| xxxxx成人.com| 国产视频在线一区二区| 国产精品丝袜久久久久久高清| 色狠狠久久aa北条麻妃| 2019中文字幕在线| 夜夜嗨av一区二区三区免费区| 色婷婷**av毛片一区| 亚洲精品国产精品国自产观看浪潮| 日韩在线观看免费全集电视剧网站| 最近更新的2019中文字幕| 国产色婷婷国产综合在线理论片a| 国产拍精品一二三| 一本色道久久88精品综合| 一本大道亚洲视频| 国产精品欧美激情在线播放| 久久精品美女视频网站| www国产91| 国产精品久久久久国产a级| 欧美网站在线观看| 亚洲精品视频在线观看视频| 国产精品极品美女在线观看免费| 97精品国产97久久久久久免费| 国产精品国产自产拍高清av水多| 日韩中文字幕在线视频| 久久久国产精彩视频美女艺术照福利| 成人在线视频福利| 美女av一区二区| 欧美日韩国产精品一区二区不卡中文| 免费91麻豆精品国产自产在线观看| 久久精品福利视频| 久久在线视频在线| 国产成人精品久久久| 8x海外华人永久免费日韩内陆视频| 国产福利精品av综合导导航|