【專業技術】關於JS的prototype

2021-02-20 程式設計師互動聯盟

概述:

在接觸JS的過程中,隨著理解的深入會逐漸的理解一些比較深奧的理論或者知識,那麼今天我們來介紹一下比較難理解的prototype和constructor。

初步理解:

在說prototype和constructor之前我們先得看幾個例子。

function name(obj){

    alert(obj)//"uw3c"

}

name("uw3c")

這是個普通的自調用的例子,大家都能理解,那麼看下一個例子:

function name(obj){

    alert(obj)//"uw3c"

}

var test = new name("uw3c")

test();

許久不見的new來了,new的作用就是"構造函數",這種方法與直接聲明的函數的區別就是:用new操作符構造出來的函數是一個對象,我們接著看下面的例子:

function uw3c(){

}

var test = new uw3c();

alert(typeof uw3c);//function

alert(typeof test);//object

uw3c是個函數,而test是個對象,那麼除了類型不一樣,還有什麼不一樣呢?

function name(){

   alert(JSON.stringify(name.prototype))//{},是個空對象

}

name();

var test = new name();

alert(JSON.stringify(test.prototype))//undefined,不存在這個對象

相信大家也看出來了,直接聲明的函數 擁有prototype這個屬性,而new 構造出來的函數不存在prototype這個屬性象。

什麼是prototype:

function定義的對象有一個prototype屬性,prototype屬性又指向了一個prototype對象,注意prototype屬性與prototype對象是兩個不同的東西,要注意區別。在prototype對象中又有一個constructor屬性,這個constructor屬性同樣指向一個constructor對象,而這個constructor對象恰恰就是這個function函數本身。 是不是很繞?用偽代碼表示如下:

var function{

    prototype:prototype{

                constructor:constructor == function

              }

}

還不明白?看圖吧:


prototype的作用:

這個prototype到底有什麼作用呢?看下面的例子:

function uw3c(){

}

uw3c.prototype.name = "a";

var test = new uw3c();

alert(test.name)//"a";

奇怪吧,明明沒有為test設置name屬性,可是為什麼會有值?

這就是prototype的功勞了,uw3c中prototype屬性中的name對象,在uw3c被new構造函數之後,被繼承到了對象test的屬性中。接著看:

var name = "js";

function uw3c(name){

    alert(this.name);//"css"

}

uw3c.prototype.name = "css";

var test = new uw3c();

test();

為什麼alert的值不是「js」?這個過程大致如下:

var test={};

uw3c.call(test);

第一步是建立一個新對象(test)。

第二步將該對象(test)內置的原型對象設置為構造函數(就是uw3c)prototype 屬性引用的那個原型對象。

第三步就是將該對象(test)作為this 參數調用構造函數(就是uw3c),完成成員設置等初始化工作。

其中第二步中出現了一個新名詞就是內置的原型對象,注意這個新名詞跟prototype對象不是一回事, 為了區別我叫它inobj,inobj就指向了函數uw3c的prototype對象。在uw3c的prototype對象中出現的任何屬性或者函數都可以在test對象中直接使用,這個就是JS中的原型繼承了。

prototype是繼承還是克隆:

看了上面的,有些人可能會認為構造一個函數是複製了原函數的prototype的屬性,在這裡大家注意一下,是繼承不是複製,請看下方的代碼:

function uw3c(){

}

uw3c.prototype.name = "b";

var test = new uw3c();

alert(JSON.stringify(test));//{}

alert(test.name);//"b"

如果是克隆應該能列印出test的一個屬性name,但是並沒有,可是卻能列印出test.name,所以是test繼承了uw3c.prototype的屬性。

prototype的優點:

講了這麼多,大家肯定會問,prototype有什麼用處,它有什麼優點?看下面代碼:

function uw3c(name){

    alert("姓名:" + name + ",年齡:" + this.age + ",性別:" + this.sex);

}

uw3c.prototype.age = 15;

uw3c.prototype.sex = "man";

var test1 = new uw3c("css");//姓名:css,年齡:15,性別:man

var test2 = new uw3c("js");//姓名:js,年齡:15,性別:man

看完這個例子大家應該明白了,使用prototype既能保留公有性,又能具有私有性。

本文轉自:http://www.uw3c.com/jsviews/js12.html

聯盟推出專業技術系列,如果有編程疑惑可按照如下格式:

專業技術+個人暱稱+具體問題

輸入到微信公眾號裡面,具有代表性的問題,聯盟將整理成文章發表

輸入js獲取所有的答疑釋惑文章,或者點擊「閱讀原文

相關焦點

  • JavaScript Prototype汙染攻擊
    prototype是一個類的屬性,所有類對象在實例化的時候將會擁有prototype中的屬性和方法一個對象的__proto__屬性,指向這個對象所在的類的prototype屬性所謂原型鏈也是指/src/core.js中:155: if ((options = arguments[ i ]) !
  • 一句有趣的JS代碼-prototype
    看過Jquery源碼的同學肯定發現以下的內容:var toStr1 = Function.prototype.call.bind
  • javascript 對象詳解:__proto__ 和 prototype 的區別和聯繫
    而 prototype屬性是只有函數才特有的屬性,當你創建一個函數時, js會自動為這個函數加上 prototype屬性,值是一個空對象。所以,函數在 js中是非常特殊的,是所謂的 一等公民。那麼 __proto__和 prototype是怎麼聯繫起來的呢?
  • Array.prototype.shift() 性能懸崖 —— 頁面JS卡死分析
    V8.Builtin_ArrayShift 即對應 JS Array.prototype.shift() 函數的實現,也就是業務調用 Array.prototype.shift() 次數過多,導致消耗了大量的時間。JS Array.prototype.shift() 函數的功能,是取出 Array 中的第一個元素,並將其刪除,同時將 Array 的長度減一。
  • 關於數組的js實用算法
    今天給大家推薦幾個關於數組的js算法使用二進位搜索算法在排序數組中查找給定元素的索引const binarySearch
  • 輕鬆理解 JS 中的面向對象,順便搞懂 prototype
    我們想要myPuppy能說話,就需要往Puppy.prototype添加說話的方法。__proto__的值就等於父類的prototype, myPuppy.__proto__指向了Puppy.prototype。
  • 利用Prototype汙染的方法繞過常見的HTML XSS檢查器
    如果未指定,默認情況下,對象的Prototype為Object.prototype。下面的代碼片段證明了這一點:  const DOMPURIFY_URL = 'https://raw.githubusercontent.com/cure53/DOMPurify/2.0.12/dist/purify.js';  (async () => {    Object.prototype.documentMode = 9;
  • 幫你徹底搞懂 JS 中的 prototype、__proto__與constructor(圖解)
    3. prototype屬性第二,接下來我們看 prototype 屬性:__proto__ === Foo.prototype,它們兩個完全一樣。那prototype屬性的作用又是什麼呢?它的作用就是包含可以由特定類型的所有實例共享的屬性和方法,也就是讓該函數所實例化的對象們都可以找到公用的屬性和方法。任何函數在創建的時候,其實會默認同時創建該函數的prototype對象。
  • 輕鬆理解 JS 中的面向對象,順便搞懂 prototype 和 __proto__
    我們想要myPuppy能說話,就需要往Puppy.prototype添加說話的方法。__proto__的值就等於父類的prototype, myPuppy.__proto__指向了Puppy.prototype。
  • JavaScript中的prototype
    javascript中的每個對象都有prototype屬性,Javascript中對象的prototype屬性的解釋是:返回對象類型原型的引用。A.prototype = new B();理解prototype不應把它和繼承混淆。A的prototype為B的一個實例,可以理解A將B中的方法和屬性全部克隆了一遍。A能使用B的方法和屬性。
  • JS規範又雙叒要更新了
    微軟 Edge(舊引擎版本)尚不支持 import() 語法,但是基於 chrome 的 Edge 發布時可能會提供支持。從 2018 年 5 月發布的 Firefox 60 開始,Firefox 可以無需標誌就使用原生模塊(ESM)。2017 年 9 月發布的 Node.js 8.5.0 實驗性地支持 ESM。
  • vm2.js沙箱逃逸
    報錯特徵Error at vm.js:1:1 at ContextifyScript.Script.runInContext (vm.js:59:29) at VM.run (/usr/src/app/node_modules/vm2/lib/main.js:219:62) at /usr/src/app/server.js:51:33 at Layer.handle [as handle_request
  • Nodejs Stream pipe 的使用與實現原理分析
    Nodejs Stream pipe 基本示例選擇 Koa 來實現這個簡單的 Demo,因為之前有人在 「Nodejs技術棧」 交流群問過一個問題,怎麼在 Koa 中返回一個 Stream,順便在下文藉此機會提下。
  • 一起來看看 Node.js v14.x LTS 中的這些新功能
    作者簡介:五月君,Software Designer,公眾號「Nodejs技術棧」作者。Node.js 是一個基於 Chrome V8 引擎的 JavaScript 運行時。image.png便利性的同時也會犧牲一些性能上的代價,關於 AsyncLocalStorage 的詳細使用介紹參見筆者的另一篇文章 「在 Node.js 中使用 async hooks
  • 第二餐:JS Hook知識整理
    (從網上抄一段,哈哈哈)Hook技術又叫做鉤子函數,在系統沒有調用該函數之前,鉤子程序就先捕獲該消息,鉤子函數先得到控制權,這時鉤子函數既可以加工處理(改變)該函數的執行行為,還可以強制結束消息的傳遞。簡單來說,就是把系統的程序拉出來變成我們自己執行代碼片段。在程序中我們可以把他理解為劫持。
  • JavaScript學習- js中的typeof/instanceof
    之前我講了js中原型和原型鏈,那衍生出來了一些其他的知識面類型判斷。我主要講三個我們經常用到的,並且在面試中很大機率會被問到的知識。
  • JS 中 call、apply、bind 那些事
    回想起之前的一些面試,幾乎每次都會問到一個js中關於call、apply、bind的問題
  • JavaScript——繼承(prototype)
    所有的 JavaScript 對象都會從一個 prototype(原型對象)中繼承屬性和方法。
  • 瘋狂Html+CSS+JS 中JS總結
    >增加了prototype屬性的類可視為繼承了原先的類(偽繼承)function Person(){...}var person = new Person();//person.wark(); 程序報錯wark不存在Person.prototype.wark = function(){...}person.wark(); //ok在prototype之前實例化的類會具有wark方法嗎?
  • js數據類型以及數據的判斷
    在中js只有7種數據類型,這其中分為基本基本類型,和引用類型。這其中基本類型包含Number、String、Boolean、Null、 Undefined、Symbol(ES6)引用類型包含Object。