国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發(fā) > JS > 正文

深入學習 JavaScript中的函數(shù)調用

2024-05-06 16:36:07
字體:
來源:轉載
供稿:網(wǎng)友

定義

可能很多人在學習 Javascript 過程中碰到過函數(shù)參數(shù)傳遞方式的迷惑,本著深入的精神,我想再源碼中尋找些答案不過在做這件事之前,首先明確幾個概念。拋棄掉值傳遞、引用傳遞等固有叫法,回歸英文:

call by reference && call by value && call by sharing

分別是我們理解的 C++ 中的引用傳遞,值傳遞。第三種比較迷惑,官方解釋是 receives the copy of the reference to object 。我用通俗的話解釋一下:

Object 可以理解為 key 的集合,Object 對 key 指向的數(shù)據(jù)是引用性質的(這里不深究是指針實現(xiàn)還是C++引用實現(xiàn)),函數(shù)接收的是一個變量的 copy,變量包含了 Object 的引用 ,是一個值傳遞。

那么很明顯,函數(shù)傳參的時候我們接收到的對象型參其實是實參的復制,所以直接更改型參的指向是不可行的;由于 Object 本身的 key 都是引用,所以修改 key 的指向是可行的。

證明

簡單來幾段代碼即可證明

Code 1: 函數(shù)能修改 key 指向的數(shù)據(jù)

let func = obj => { obj.name = 'Dosk' };let obj = {name : 'Alxw'};console.log(obj); //{ name: 'Alxw' }func(obj)console.log(obj); //{ name: 'Dosk' }

Code 2: 函數(shù)不能修改 obj

let func = obj => { obj = {} };let obj = {name : 'Alxw'};console.log(obj); //{ name: 'Alxw' }func(obj)console.log(obj); //{ name: 'Alxw' }

Code 3: 內部 obj 和外部 === 結果相等

let def = {name : 'Alxw'};let func = obj => { console.log(obj === def) };func(def); //true

所以第三段代碼可能有疑問了,既然 obj 是 def 的復制,為什么 === 操作還能夠為真?不是說 === 操作對于 Object 比較的是在內存中的地址么,如果是復制應該是 false 才對啊?

所以我們回到 Google V8 的源碼來看這件事。

深入 Google V8

我們來看看源碼里嚴格等于操作代碼部分:

bool Object::StrictEquals(Object* that) { if (this->IsNumber()) {  if (!that->IsNumber()) return false;  return NumberEquals(this, that); } else if (this->IsString()) {  if (!that->IsString()) return false;  return String::cast(this)->Equals(String::cast(that)); } else if (this->IsSimd128Value()) {  if (!that->IsSimd128Value()) return false;  return Simd128Value::cast(this)->Equals(Simd128Value::cast(that)); } return this == that;}

看起來應該是最后一種情況,理論上如果 def 和 obj 是不同的對象,那么應該返回 false 才對,這不是推翻了上文所述么?其實不,忽略了一件事,即 Google V8 內部在實例化一個 Object 的時候,本身就是動態(tài)實例化,而我們知道在編譯型語言中如果動態(tài)實例化只能夠在堆內存上,即只能夠指針引用。這個結論是的證明涉及到 Local 、Handle 等 class 的實現(xiàn),我覺得太麻煩,有一個簡單的證明方式,即搜索源碼得到所有調用 Object::StrictEquals 的地方都是直接傳入而沒有取地址操作。

不過有人會問,既然是值傳遞的變量包含 Object 的引用,理論上也能夠修改 Object 才對,為什么第三段代碼不能修改呢?

很簡單的道理,因為我們在 Javascript 語言邏輯層次上的所謂的操作,只不過是在調用 Google V8 的實例方的法而已,根本不可能操作到這一地步(當然,潛在的 BUG 不算的 -。-)

重新定義

我覺得到這里可以給 call by sharing 重新解釋一下了:

的確,傳遞的時候是值傳遞,但是內容包含了 Object 的指針,而且不能夠修改這個指針,他是多個變量共享的。

另一種簡單的證明

來來來,看源碼

V8_DEPRECATE_SOON("Use maybe version",         Local<Value> Call(Local<Value> recv, int argc,                  Local<Value> argv[]));V8_WARN_UNUSED_RESULT MaybeLocal<Value> Call(Local<Context> context,                       Local<Value> recv, int argc,                       Local<Value> argv[]);

上面的是即將棄用的接口,碰巧我看到的這個版本代碼包含大量的這種即將棄用的代碼,看看就好。重點是第二個接口,是函數(shù)的唯一的調用的接口。里面的 Local<Value> 最終會調用 C++ 的位復制,所以可以簡單的證明就是值傳遞。

可能是重點

別忘了,我們定義的的變量都是類似 Handle<Object> 這種形式的,所以它們之間對象才是共享的,我們所說的 Javascript 里面變量并不直接指的是 Object 的實例!!!

最后的最后

總之理解起來可能很費勁甚至有錯誤,但是在 Javascript 語言層次上能夠確定了特性,這才是重要的。

以上所述是小編給大家介紹的Javascript中的函數(shù)調用,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VeVb武林網(wǎng)網(wǎng)站的支持!


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 宜都市| 泗阳县| 冀州市| 赣州市| 江津市| 武宣县| 密云县| 通州市| 沈阳市| 崇左市| 淅川县| 慈溪市| 称多县| 都匀市| 睢宁县| 平潭县| 博湖县| 云阳县| 德保县| 青川县| 滦南县| 许昌市| 嵩明县| 镇巴县| 峨边| 阿拉善左旗| 那坡县| 奉节县| 宁海县| 山西省| 中卫市| 庆云县| 河北区| 重庆市| 汾阳市| 迭部县| 沙河市| 云霄县| 凌海市| 浮山县| 桦甸市|