java裏面,new 運算符是用來實例化一個類,從而在內存中分配一個實例對象。 但在 javascript 中,原型語言沒類,只有對象與原型鏈繼承

JavaScript 中 new 錶達式的作用是生成一個對象。

new 運算符創建一個用戶定義的對象類型的實例或具有構造函數的內置對象的實例

new 關鍵字會進行如下的操作:

  • 創建一個空對象(即{});

  • 鏈接該對象(即設置該對象的構造函數)到另一個對象 ;

  • 將步驟1新創建的對象作為this的上下文 ;

  • 如果該函數沒有返回對象,則返回this。

根據這個步驟,手工實現new

function create(){
  //創建一個空對象
  let obj = new Object();
  //獲取構造函數  // let args = [].slice.call(arguments); let Fun = args.shift();
  let Constructor = [].shift.call(arguments);
  //鏈接到原型
  obj.__proto__ = Constructor.prototype;
  //綁定this值,使用apply,將構造函數中的this指向新對象,這樣新對象就可以訪問構造函數中的屬性和方法
  let result = Constructor.apply(obj,arguments);
  //返回新對象
  return typeof result === "object" ? result : obj;//如果返回值是一個對象就返回該對象,否則返回構造函數的一個實例對象
}

在javascript中, 通過new可以產生原對象的一個實例對象,而這個實例對象繼承了原對象的屬性和方法。因此,new存在的意義在於它實現了javascript中的繼承

在《JavaScript模式》這本書中,new的過程說的比較直白,當我們new一個構造器,主要有三步:

• 創建一個空對象,將它的引用賦給 this,繼承函數的原型。

• 通過 this 將屬性和方法添加至這個對象

• 最後返回 this 指向的新對象,也就是實例(如果沒有手動返回其他的對象)

當我們new一個構造函數,得到的實例繼承了構造器的構造屬性(this.name這些)以及原型上的屬性

// ES5構造函數
let Parent = function (name, age) {
    //1.創建一個新對象,賦予this,這一步是隱性的,
    // let this = {};
    //2.給this指向的對象賦予構造屬性
    this.name = name;
    this.age = age;
    //3.如果沒有手動返回對象,則默認返回this指向的這個對象,也是隱性的
    // return this;  //this的創建與返回是隱性的
};
const child = new Parent();

但上述這個解釋我覺得不够完美,它只描述了構造器屬性是如何塞給實例,沒說原型上的屬性是如何給實例繼承的。

我在winter大神的重學前端專欄中,看到了比較符合我心意的,同時也是符合原理的描述:

• 以構造器的prototype屬性為原型,創建新對象;

• 將this(也就是上一句中的新對象)和調用參數傳給構造器,執行;

• 如果構造器沒有手動返回對象,則返回第一步創建的新對象,如果有,則舍弃掉第一步創建的新對象,返回手動return的對象。

new過程中會新建對象,此對象會繼承構造器的原型與原型上的屬性,最後它會被作為實例返回這樣一個過程

以直觀的方式來理解的話,關鍵詞 new 之後所寫的是類名。不過正如此前說明,JavaScript 中沒有類的概念,所以,根據 JavaScript 的語法規則,new 之後所寫的是函數名。在 new 之後寫函數名的話,就會把該函數作為構造函數來進行調用

在 JavaScript 的語言特性中沒有“類”的概念,為了便於理解,將用類 這個詞來稱呼那些可以被視作“類”的概念。來稱呼那些實際上將會調 用構造函數的 Function 對象。此外,在强調對象是通過調用構造函數而生成的時候,會將這些被生成的 對象稱作對象實例以示區別。

雖然在 JavaScript 中沒有類的概念,但將 new 之後所寫的標識符(函數名)看作是類名, 也並沒有什麼概念上的問題。也就是說,完全可以認為,上文中代碼 new Object() 的作用是生成一個 Object 類的實例。

對類的功能的整理

接口

說明

函數或是構造函數的調用

-

類的屬性

相當於Java 中的static 方法或是static 域

prototype 對象的屬性

相當於Java 中的實例方法

實例屬性

相當於Java 中的實例域

類的屬性是一個類自身的屬性,例如,String 類的屬性是 String 類的對象自身的屬性。如果是函數的話,則可以像 String.fromCharCode(0x41) 這樣來使用。如果用更加直觀一些的說法來講,這就相當於 Java 或 C++ 中的 static 方法。

prototype 對象的屬性和實例屬性,都是以對象實例的形式來進行訪問的。以 String 類為例,可以以 str.trim() 或是 str.length 的方式,來使用引用了 String 對象(對象實例)的變量 str。

prototype 對象的屬性與實例屬性之間的不同點在於是否進行了繼承。例如,String 對象的 trim 方法,其實是 String.prototype 對象的屬性。這種以實例來繼承屬性的方式被稱為原型繼承。

實現一個簡單的new方法

//自己定義的new方法
let newMethod = function (Parent, ...rest) {
    // 1.以構造器的prototype屬性為原型,創建新對象;
    let child = Object.create(Parent.prototype);
    // 2.將this和調用參數傳給構造器執行
    let result = Parent.apply(child, rest);
    // 3.如果構造器沒有手動返回對象,則返回第一步的對象
    return typeof result  === 'object' ? result : child;
};

參考文章:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/new

JavaScript深入之new的模擬實現 https://github.com/mqyqingfeng/Blog/issues/13

js new一個對象的過程,實現一個簡單的new方法 https://www.cnblogs.com/echolun/p/10903290.html

js手動實現new方法 https://www.jianshu.com/p/9cee6a703e01

轉載本站文章《JavaScript new 關鍵詞解析及原生實現 new》,
請注明出處:https://www.zhoulujun.cn/html/webfront/ECMAScript/js/2020_0630_8498.html

JavaScript new 關鍵詞解析及原生實現 new的更多相關文章

  1. [轉]javascript eval函數解析json數據時為什加上圓括號eval("("+data+")")

    javascript eval函數解析json數據時為什麼 加上圓括號?為什麼要 eval這裏要添加 “("("+data+")");//”呢?   原因在於: ...

  2. JavaScript運行原理解析

    原文:1.http://blog.csdn.net/liaodehong/article/details/50488098 2.Stack的三種含義 (阮一峰) 3. http://lib.csdn. ...

  3. [WebKit內核] JavaScript引擎深度解析--基礎篇(一)字節碼生成及語法樹的構建詳情分析

    [WebKit內核] JavaScript引擎深度解析--基礎篇(一)字節碼生成及語法樹的構建詳情分析 標簽: webkit內核JavaScriptCore 2015-03-26 23:26 2285 ...

  4. 异類的Javascript處理和解析URL的方式

    通常來說,我們使用Javascript處理和解析URL是使用location對象.在今天這個代碼小技巧中,我們使用另外一個比較异類的方式處理和解析URL. 代碼如下: function parseUR ...

  5. async和await關鍵詞用於定義原生的協程

    #python為了將語義變得更加明確,就引入了async和await關鍵詞用於定義原生的協程 # async def downloader(url): # return "xxxx" ...

  6. 松軟科技Web課堂:JavaScript this 關鍵詞

    實例 var person = { firstName: "Bill", lastName : "Gates", id : 678, fullName : fu ...

  7. Javascript面試題解析

    Javascript的一些面試題讓很多同學感到頭疼,下面就根據兄弟連教育 )畢業學員面試遇到的面試題,給大家做一個簡單的分享,希望對初入職場的你們有一些幫助:Javascript面試題解析. 第一題 ...

  8. 44個 Javascript 變態題解析 (下)

    承接上篇 44個 Javascript 變態題解析 (上) 第23題 [1 < 2 < 3, 3 < 2 < 1] 這個題也還可以. 這個題會讓人誤以為是 2 > 1 & ...

  9. JavaScript this 關鍵詞

    this是什麼呢? JavaScript this 關鍵詞指的是它所屬的對象. 它擁有不同的值,具體取决於它所使用的比特置: 在方法中,this 指的是所有者對象. 單獨的情况下,this 指的是全局對 ...

  10. 使用原生javascript和jQuery解析json數據

    JSON(JavaScript Object Notation)是一種輕量級的數據交換格式. JSONM文件中包含了關於“名稱”和“值”的信息. 有時候我們需要讀取JSON格式的數據文件,在jQuer ...

隨機推薦

  1. Ubuntu 部署Postgresql

    安裝組件 客戶端安裝 sudo apt-get install postgresql-client 服務器安裝 sudo apt-get install postgresql postgresql-c ...

  2. AlwaysOn--Backup Preference

    AlwaysOn group的一個新特性是允許在secondary replica進行backup,將backup的負載從primary replica上移除去. 並且提供了Backup prefer ...

  3. asp.net MVC中獲取當前URL/Controller/Action

    一.獲取URL(ASP.NET通用): [1]獲取完整url(協議名+域名+虛擬目錄名+文件名+參數) string url=Request.Url.ToString(); [2]獲取虛擬目錄名+頁面 ...

  4. Javascript倒計時組件new TimeSpan(hours, minutes, minutes)

    function TimeSpan(h, m, s) { this.h = Number(h); this.m = Number(m); this.s = Number(s); } TimeSpan. ...

  5. UIScrollView子控件的布局

    scorllView內部子控件添加約束的注意點: 1.子控件的尺寸不能通過UIScrollView來計算 *比如可以設置固定值 (width==100 height ==100) *比如可以相對於UI ...

  6. WP開發筆記——字符串 轉 MD5 加密

    將字符串進行MD5加密,返回加密後的字符串. 從這裏下載Md5.cs文件:http://pan.baidu.com/s/1hq3gpnu. 添加到Windows Phone 7項目中,在代碼裏面這樣調 ...

  7. IOS開發根據字體大小等獲取文字所占的高度

    Model *model = self.modelArr[indexPath.row]; //根據label文字獲取CGRect NSMutableParagraphStyle *paragraphS ...

  8. FastDFS 文件上傳工具類

    FastDFS文件上傳工具類 import org.csource.common.NameValuePair; import org.csource.fastdfs.ClientGlobal; imp ...

  9. jar包獲取資源文件

    背景 寫的一個spring boot項目打成jar包部署運行下,打成jar包,提示找不到資源文件,如下圖: 直接通過idea是可以運行的,但打成jar包後提示找不到資源文件,簡單查閱後了解到是因為ja ...

  10. AlloyTouch全屏滾動插件搞定順滑H5頁

    使用姿勢 在設計全屏滾動插件的時候,希望開發者幾乎: 不用寫任何脚本快速生成精致H5 支持PC滾輪和移動觸摸 酷炫的轉場動效 靈活的時間軸管理 一切皆可配置 但是不寫脚本肯定沒有靈活性咯?!不是的.這 ...