目錄
0 怎麼理解物件導向
1 建立物件的方式
instanceof 的原理是什麼呢?先來看看使用
首頁 web前端 js教程 javascript原型和繼承是面試必會的

javascript原型和繼承是面試必會的

Dec 01, 2020 pm 05:40 PM
javascript

javascript欄位介紹面試必會的原型與繼承

javascript原型和繼承是面試必會的

#相關免費學習推薦:javascript(影片)

本文從以下幾個面向著手

  • 0怎麼理解物件導向
  • 1建立物件的方式
  • 2記住原型鏈的小技巧
  • #3instanceof 模擬實作
  • 4new關鍵字模擬實作
  • 5繼承的實作(逐步實作)

0 怎麼理解物件導向

其實我也不知道咋回答這問題,我只知道,面試官問這個後,就表示他要問一堆繼承的問題了。以下是引用週老師的一段說詞。

"物件導向是一種程式設計思想與面向過程是對應的一般的語言都是物件導向的js本身也是基於物件導向建構出來的,例如js本身就有很多內建類,Promise就是,可以new Promise來建立一個實例,來管理非同步程式設計。還有vue 也是,平常都是建立vue的實例啊。"

1 建立物件的方式

##1.物件字面量

var o1 = {name: 'o1'}
var o2 = new Object({name: 'o2'})
登入後複製
2.透過建構子

var M = function(name){
    this.name = name
}
var o3 = new M('o3')
登入後複製
3.Object.create

var o4 = Object.create(p)
登入後複製
2 記住原型鏈的小技巧

##記憶總是有規律的,如高中時期學的三角函數,需要背公式很多,強行去背全部的公式是容易混亂的。不過如果把核心的幾點背牢,其餘的公式只需要稍加推導即可。關於原型鏈也是一樣,有幾點在開始就記住的話,後面就不會亂了。原型鏈中關鍵概念:
建構子

實例constructor__ proto__prototype, 首先要記住他們的關係

實例(物件)有
    proto
  • , 實例(物件)沒有prototype建構子有prototype ,同時prototype又是對象,那麼prototype即滿足上面一條,除了擁有
  • proto
  • 外,還含有constructor構造函數的prototype的constructor就是指向構造函數本身,即上例中M.prototype. constructor === M
上面3點請先牢記,後面所總結的完整繼承和這有緊密的關聯

其實
建構子

實例constructor__ proto__prototype 的關係已經在上面的例子和3點介紹中介紹完了。不妨再回顧一下

    建構子即普通函數,只不過前邊有new 關鍵字
  1. 透過
  2. new

    建構函式 ,產生的物件即為實例。

  3. 以上面產生o3實例為例子
  4.  o3.__proto__ === M.prototype  //true
    
     o3.prototype   //undefined
    
     o3.__proto__ === M.prototype //true
    登入後複製

  5. #o3實例本身並無constructor,不過會藉助原型鏈向上查找,即,
  6.  o3.constructor === M.prototype.constructor  // true
    
     o3.constructor === M //true
    登入後複製

小結理清這幾個關鍵字的關係後,原型鏈就明朗很多了

3 instanceof 模擬實作

instanceof 的原理是什麼呢?先來看看使用

[] instanceof Array  // true
登入後複製

即左邊是對象,右邊是類型,instanceof 就是要判斷右邊類型的prototype,是否在左邊實例的原型鏈上,如下例子所示

[].__proto__ === Array.prototype //true
Array.prototype.__proto__ === Object.prototype //true
Object.prototype__proto__ //null
登入後複製

#那麼依據這個想法來實現一下instanceof吧,一定會印象更加深刻

function myInstanceof2(left, right){
    if(left === null || left === undefined){
        return false
    }
    if(right.prototype === left.__proto__) {
        return true
    }

    left = left.__proto__
    return myInstanceof2(left, right)
}

console.log(myInstanceof2([], Array))
登入後複製
4 new 模擬實現(簡要版)

new的過程發生了什麼?

    產生空物件
  1. 這個空物件的
  2. proto

    賦值為建構子的prototype

  3. 綁定this指向
  4. 回傳這個物件
  5.  // 构造函数
     function M(name){
        this.name = name
     }
     // 原生new
     var obj = new M('123')
    
     // 模拟实现
     function create() {
       // 生成空对象
       let obj = {}
       // 拿到传进来参数的第一项,并改变参数类数组
       let Con = [].shift.call(arguments)
       // 对空对象的原型指向赋值
       obj.__proto__ = Con.prototype
       // 绑定this 
       //(对应下面使用来说明:Con是参数第一项M,
       // arguments是参数['123'],
       // 就是 M方法执行,参数是'123',执行这个函数的this是obj)
       let result = Con.apply(obj, arguments)
       return result instanceof Object ? result : obj
     }
    
     var testObj = create(M, '123')
     console.log('testObj', testObj)
    登入後複製

  6. 5 繼承的實作(逐步實作)

一步一步來,從簡到繁,更能直觀發現繼承的原理與缺點

    #建構方法核心Parent1.call(this)
  1.  // 构造方法方式
     function Parent1(){
        this.name = 'Parent1'
     }
     Parent1.prototype.say = function () {
        alert('say')
     }
     function Child1(){
        Parent1.call(this)
        this.type = 'type'
     }
    
     var c1 = new Child1()
     c1.say() //报错
    登入後複製

缺點: 只能繼承父類別建構子內部屬性,無法繼承父類別建構子原型物件上屬性

##思考: 為什麼call 實現了繼承,call本質是什麼?

只借助原型繼承核心Child2.prototype = new Parent2()
     // 原型
     function Parent2(){
        this.name = 'Parent2'
        this.arr = [1,2]
     }
     Parent2.prototype.say = function () {
        alert('say')
     }
     function Child2(){
        // Parent2.call(this)
        this.type = 'type'
     }
     Child2.prototype = new Parent2()
    
     var c21 = new Child2()
     var c22 = new Child2()
    
     c21.say()
     c21.arr.push('9')
     console.log('c21.arr : ', c21.arr)
     console.log('c22.arr : ', c22.arr)
    登入後複製
  1. 缺點: c21.arr 與c22.arr對應的是同一個引用

思考:為什麼這麼寫是同一個引用?

組合繼承1
  1. 把上面兩個繼承方式的優點合併起來,缺點都拋棄掉
 function Parent3(){
    this.name = 'Parent3'
    this.arr = [1,2]
}
Parent3.prototype.say = function () {
    alert('say')
}
function Child3(){
    Parent3.call(this)
    this.type = 'type'
}
Child3.prototype = new Parent3()

var c31 = new Child3()
var c32 = new Child3()

c31.say()
c31.arr.push('9')
console.log('c31.arr : ', c31.arr)
console.log('c31.arr : ', c32.arr)
登入後複製

思考: 這麼寫就沒有問題了嗎?

答 : 生成一个实例要执行 Parent3.call(this) , new Child3(),也就是Parent3执行了两遍。

  1. 组合继承2

改变上例子 的

  Child3.prototype = new Parent3()
登入後複製

  Child3.prototype = Parent3.prototype
登入後複製

缺点 : 很明显,无法定义子类构造函数原型私有的方法

  1. 组合继承优化3 再次改变上例子 的

    Child3.prototype = Parent3.prototype
    登入後複製

   Child3.prototype = Object.create(Parent3.prototype)
登入後複製

问题就都解决了。 因为Object.create的原理是:生成一个对象,这个对象的proto, 指向所传的参数。

思考 :是否还有疏漏?一时想不起来的话,可以看下这几个结果

console.log(c31 instanceof Child3) // true
console.log(c31 instanceof Parent3) // true
console.log(c31.constructor === Child3) // false
console.log(c31.constructor === Parent3) // true
登入後複製

所以回想起文章开头所说的那几个需要牢记的点,就需要重新赋值一下子类构造函数的constructor: Child3.prototype.constructor = Child3,完整版如下

function Parent3(){
    this.name = 'Parent3'
    this.arr = [1,2]
}
Parent3.prototype.say = function () {
    alert('say')
}
function Child3(){
    Parent3.call(this)
    this.type = 'type'
}

Child3.prototype = Object.create(Parent3.prototype)
Child3.prototype.constructor = Child3

var c31 = new Child3()
var c32 = new Child3()

c31.say()
c31.arr.push('9')
console.log('c31.arr : ', c31.arr)
console.log('c31.arr : ', c32.arr)

console.log('c31 instanceof Child3 : ', c31 instanceof Child3)
console.log('c31 instanceof Parent3 : ', c31 instanceof Parent3)
console.log('c31.constructor === Child3 : ', c31.constructor === Child3)
console.log('c31.constructor === Parent3 : ', c31.constructor === Parent3)
登入後複製

5 es6的继承

class Parent{
  constructor(name) {
    this.name = name
  }
  getName(){
    return this.name
  }
}

class Child{
  constructor(age) {
    this.age = age
  }
  getAge(){
    return this.age
  }
}
登入後複製

es6继承记住几个注意事项吧

  • 1 构造函数不能当普通函数一样执行 Parent() 是会报错的
  • 2 不允许重定向原型 Child.prototype = Object.create(Parent.prototype) 无用
  • 3 继承写法如下,上面的Child类想继承父类,改成如下写法就好

javascript原型和繼承是面試必會的javascript原型和繼承是面試必會的


注意写了extends关键字,constructor中就必须写super(),打印结果如下:

javascript原型和繼承是面試必會的

以上是javascript原型和繼承是面試必會的的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
1 個月前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

javascript如何使用insertBefore javascript如何使用insertBefore Nov 24, 2023 am 11:56 AM

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

如何在JavaScript中取得HTTP狀態碼的簡單方法 如何在JavaScript中取得HTTP狀態碼的簡單方法 Jan 05, 2024 pm 01:37 PM

JavaScript中的HTTP狀態碼取得方法簡介:在進行前端開發中,我們常常需要處理與後端介面的交互,而HTTP狀態碼就是其中非常重要的一部分。了解並取得HTTP狀態碼有助於我們更好地處理介面傳回的資料。本文將介紹使用JavaScript取得HTTP狀態碼的方法,並提供具體程式碼範例。一、什麼是HTTP狀態碼HTTP狀態碼是指當瀏覽器向伺服器發起請求時,服務

See all articles