這篇文章主要介紹了關於JS中new調用函數的原理介紹,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下
JavaScript 中經常使用構造函數創建物件(透過new
操作符呼叫一個函數),那在使用new
呼叫一個函數的時候到底發生了什麼事?先看幾個例子,再解釋背後發生了什麼事。
1)看三個例子
1.1 無return 語句
#建構子最後沒有return
語句,這也是使用建構子時預設情況,最後會傳回一個新對象,如下:
function Foo(age) { this.age = age; } var o = new Foo(111); console.log(o);
這是常見的使用建構子建立物件的過程,列印出來的是{age: 111}
。
1.2 return 物件類型資料
建構子最後return
物件類型資料:
function Foo(age) { this.age = age; return { type: "我是显式返回的" }; } var o = new Foo(222); console.log(o);
列印出來的是{type: '我是顯式回傳的'}
,也就是說,return
之前的工作都白做了,最後回傳return
後面的物件。
1.3 return 基本型別資料
那是不是只要建構函式體內最後有 return
,回傳都是 return
後面的資料呢?
我們看下傳回基本型別資料的情況:
function Foo(age) { this.age = age; return 1; } var o = new Foo(333); console.log(o);
印出來的是{age: 333}
,而沒有return
時效果一樣。跟預期不一樣,背後你原理看下面分析。
2)背後原理
2.1 非箭頭函數的情況
當使用new
運算子建立物件是,ES5 官方文件在函數定義 一節中做瞭如下定義13.2.2 [[Construct]]
:
When the [[Construct]]
internal method for a Function
object F
is called with a possibly empty list of arguments, the following steps are taken:
Let obj be a newly created native ECMAScript object.
Set all the internal methods of obj as specified in 8.12.
Set the [[Class] ] internal property of obj to Object.
Set the [[Extensible]] internal property of obj to true.
#Let proto be the value of calling the [[Get]] internal property of F with argument "prototype".
- ##If Type(proto) is Object, set the
[[Prototype]] internal property of obj to proto.
- If Type(proto) is not Object, set the [[Prototype]] internal property of obj to the standard built-in
Object prototype object as described in 15.2.4.
- Let result be the result of calling the [[Call]] internal property of F,
providing obj as the this value and providing the argument list passed into [[Construct]] as args.
#If Type(result) is Object then return result.
- Return obj.
F,將其傳回值賦給
result;其中,
F執行時的實參為傳遞給
[[Construct]](即
F本身)的參數,
F內部
this指向
obj;
9)如果
result是
Object類型,返回
result;
這也解釋瞭如果建構子明確傳回物件類型,則直接傳回這個對象,而不是傳回最開始建立的對象。
最後在看第10 步:10)如果F傳回的不是物件類型(第9 步不成立),則傳回已建立的物件
obj。
如果建構函式沒有明確傳回物件類型(明確傳回基本資料型別或直接不回傳),則傳回最開始建立的物件。
2.2 箭頭函數的情況那如果建構子是箭頭函數怎麼辦? 箭頭函數中沒有[[Construct]] 方法,不能使用
new 調用,會報錯。
[[Construct]] 就是指建構子本身。
new 進行調用,背後發生了什麼,上節英文講述的很清楚了,再用中文描述如下:
1)创建 ECMAScript 原生对象 obj
;
2)给 obj
设置原生对象的内部属性;(和原型属性不同,内部属性表示为 [[PropertyName]]
,两个方括号包裹属性名,并且属性名大写,比如常见 [[Prototype]]
、[[Constructor]]
)
3)设置 obj
的内部属性 [[Class]]
为 Object
;
4)设置 obj
的内部属性 [[Extensible]]
为 true
;
5)将 proto
的值设置为 F
的 prototype
属性值;
6)如果 proto
是对象类型,则设置 obj
的内部属性 [[Prototype]]
值为 proto
;(进行原型链关联,实现继承的关键)
7)如果 proto
是不对象类型,则设置 obj
的内部属性 [[Prototype]]
值为内建构造函数 Object 的 prototype
值;(函数 prototype
属性可以被改写,如果改成非对象类型,obj
的 [[Prototype]]
就指向 Object 的原型对象)
8)9)10)见上节分析。(决定返回什么)
对于第 7 步的情况,见下面代码:
function Foo(name) { this.name = name; } var o1 = new Foo("xiaoming"); console.log(o1.__proto__ === Foo.prototype); // true // 重写构造函数原型属性为非对象类型,实例内部 [[Prototype]] 属性指向 Object 原型对象 // 因为实例是一个对象类型的数据,默认会继承内建对象的原型, // 如果构造函数的原型不满足形成原型链的要求,那就跳过直接和内建对象原型关联 Foo.prototype = 1; var o2 = new Foo("xiaohong"); console.log(o2.__proto__ === Foo.prototype); // false console.log(o2.__proto__ === Object.prototype); // true
3.2 更简洁的语言描述
若执行 new Foo()
,过程如下:
1)创建新对象 o
;
2)给新对象的内部属性赋值,关键是给[[Prototype]]
属性赋值,构造原型链(如果构造函数的原型是 Object 类型,则指向构造函数的原型;不然指向 Object 对象的原型);
3)执行函数 Foo
,执行过程中内部 this
指向新创建的对象 o
;
4)如果 Foo
内部显式返回对象类型数据,则,返回该数据,执行结束;不然返回新创建的对象 o
。
4)几点说明
4.1 判断是否是 Object 类型
关于一个数据是否是 Object
类型,可以通过 instanceof
操作符进行判断:如果 x instanceof Object
返回 true
,则 x
为 Object
类型。
由上可知,null instanceof Object
返回 false
,所以 null
不是 Object
类型,尽管typeof null
返回 "Object"。
4.2 instanceof 原理
instanceof
的工作原理是:在表达式 x instanceof Foo
中,如果 Foo
的原型(即 Foo.prototype
)出现在 x
的原型链中,则返回 true
,不然,返回 false
。
因为函数的原型可以被改写,所以会出现在 x
通过 Foo
new 出来之后完全改写 Foo
的原型 x instanceof Foo
返回 false
的情况。因为实例创建之后重写构造函数原型,实例指向的原型已经不是构造函数的新的原型了,见下面代码:
const Foo = function() {}; const o = new Foo(); o instanceof Foo; // true // 重写 Foo 原型 Foo.prototype = {}; o instanceof Foo; // false
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
以上是關於JS中new調用函數的原理介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr

Node.js擅長於高效I/O,這在很大程度上要歸功於流。 流媒體匯總處理數據,避免內存過載 - 大型文件,網絡任務和實時應用程序的理想。將流與打字稿的類型安全結合起來創建POWE

Python和JavaScript在性能和效率方面的差異主要體現在:1)Python作為解釋型語言,運行速度較慢,但開發效率高,適合快速原型開發;2)JavaScript在瀏覽器中受限於單線程,但在Node.js中可利用多線程和異步I/O提升性能,兩者在實際項目中各有優勢。

JavaScript起源於1995年,由布蘭登·艾克創造,實現語言為C語言。 1.C語言為JavaScript提供了高性能和系統級編程能力。 2.JavaScript的內存管理和性能優化依賴於C語言。 3.C語言的跨平台特性幫助JavaScript在不同操作系統上高效運行。

JavaScript在瀏覽器和Node.js環境中運行,依賴JavaScript引擎解析和執行代碼。 1)解析階段生成抽象語法樹(AST);2)編譯階段將AST轉換為字節碼或機器碼;3)執行階段執行編譯後的代碼。

Python和JavaScript的未來趨勢包括:1.Python將鞏固在科學計算和AI領域的地位,2.JavaScript將推動Web技術發展,3.跨平台開發將成為熱門,4.性能優化將是重點。兩者都將繼續在各自領域擴展應用場景,並在性能上有更多突破。

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

WebStorm Mac版
好用的JavaScript開發工具

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

Atom編輯器mac版下載
最受歡迎的的開源編輯器