JS中的求值策略

xiaowoniu發表於2020-03-22

一、是啥

求值策略(Evaluation strategy)是啥?
是一種策略
是一種決定什麼時候,用什麼方式計算函式引數的策略
是一種分為嚴格求值和非嚴格求值的策略

JS中的求值策略

二、為啥

為啥會需要這樣一種策略?

定義一個函式

function sum(x, y) {
    return x + y;
}
複製程式碼

呼叫它

sum(8, 3);
複製程式碼

這時候,問題產生了,程式語言需要在啥時候,用什麼方式計算函式引數呢?這就是求值策略存在的意義。 下面用虛擬碼來解釋一下嚴格求值和非嚴格求職的執行機制

//嚴格求值
function sum(x=8, y=3) {
    return x + y;
}
//非嚴格求值
function sum(x, y) {
    return (x=8) + (y=3);
}
複製程式碼

正如所見,嚴格求值是引數在進入函式之前計算,而非嚴格求值則是在引數被呼叫的時候進行計算,不呼叫,不進行多餘計算。

三、js?

JS中的求值策略是哪一種呢?
先放結論,JavaScript 語言採用嚴格求值策略。
將這一結論作為前提,我們再來解釋一下嚴格求值策略的特性。針對js中的基本資料型別和引用資料型別,從現象倒推,可以總結為傳值呼叫,傳引用呼叫和傳共享物件呼叫。 這裡,我借鑑一下Javascript中的求值策略這篇文章中的程式碼示例

function magic(num, objectA, objectB) {
     num = num * 6;
     objectA = {name: 'AA'} 
     objectB.name = 'BB';
}
const num = 1;
const objectA = {name: 'A'};
const objectB = {name: 'B'};
magic(num, objectA, objectB);
console.log(num); // 1
console.log(objectA); // {name: "A"}
console.log(objectB); // {name: "BB"} 
複製程式碼

console.log(num); // 1 代表傳值呼叫。 引數的num=1,是複製了數字1,所以函式內部的操作不會影響外部的num值。

console.log(objectB);// {name: "BB"} 則代表傳引用呼叫。 引數中的objectB={name: 'B'},只是複製objectB的引用,實際還是指向相同的地址,所以函式內部修改objectB的屬性,外部的objectB也會受到影響。

console.log(objectA); // {name: "A"} 代表傳共享物件呼叫。 引數objectA={name: 'A'},與函式裡的操作objectA = {name: 'AA'},使函式內部和外部是兩個獨立的object,互不影響,所以函式內部的操作也不會影響外部objectA的值。


看了好幾篇文章,這裡是我自己的理解,如有誤,請指正。

延伸

惰性求值
Thunk函式

參考

Thunk 函式的含義和用法
Javascript中的求值策略
求值策略

相關文章