JS高階之路之 作用域(二)

2021-08-21 03:40:54 字數 2739 閱讀 1932

最小授權原則

最小授權原則是指在軟體設計中,應該最小限度地暴露必要內容,而將其他內容都「隱藏」起來,比如某個模組或物件的 api 設計。

這個原則可以延伸到如何選擇作用域來包含變數和函式。如果所有變數和函式都在全域性作 用域中,當然可以在所有的內部巢狀作用域中訪問到它們。但這樣會破壞前面提到的最小 特權原則,因為可能會暴漏過多的變數或函式,而這些變數或函式本應該是私有的,正確 的**應該是可以阻止對這些變數或函式進行訪問的。

例如:

function

dosomething(a)

function

dosomethingelse(a)

varb;

dosomething( 2 ); // 15

在這個**片段中,變數 b 和函式 dosomethingelse(..) 應該是 dosomething(..) 內部具體 實現的「私有」內容。給予外部作用域對 b 和 dosomethingelse(..) 的「訪問許可權」不僅 沒有必要,而且可能是「危險」的,因為它們可能被有意或無意地以非預期的方式使用, 從而導致超出了 dosomething(..) 的適用條件。更「合理」的設計會將這些私有的具體內容隱藏在 dosomething(..) 內部,

例如:

function

dosomething(a)    

varb;    

b=a+dosomethingelse( a

*2 );    

console.log( b

*3 );

}dosomething( 2 ); // 15

現在,b 和 dosomethingelse(..) 都無法從外部被訪問,而只能被 dosomething(..) 所控制。 功能性和最終效果都沒有受影響,但是設計上將具體內容私有化了,設計良好的軟體都會 依此進行實現。

規避衝突

當我們的程式**逐漸多起來,難免會出現變數衝突。那麼如何規避衝突就顯得額外重要。

函式可以把識別符號嚴謹的"隱藏"起來,外部無法訪問到,利用這個特性我們可以很好的規避衝突。

function

foo()

function

bar()

foo和bar中定義了相同的變數a,但是卻不會相互造成影響。因為函式可以很好的把識別符號"隱藏"起來。

變數衝突的乙個典型例子存在於全域性作用域中。當程式中載入了多個第三方庫時,如果它 們沒有妥善地將內部私有的函式或變數隱藏起來,就會很容易引發衝突。 這些庫通常會在全域性作用域中宣告乙個名字足夠獨特的變數,通常是乙個物件。這個物件 被用作庫的命名空間,所有需要暴露給外界的功能都會成為這個物件(命名空間)的屬 性,而不是將自己的識別符號暴漏在頂級的詞法作用域中。

例如:

var

mylibrary

= }

函式宣告 vs 函式表示式

//函式宣告function foo() {}

//函式表示式var foo = function () {};

(function() {})();

具名函式 vs 匿名函式
function

foo() {}

varfoo

=function

bar() {}

settimeout( function

foo() {} )+

function

foo() {}();

需要注意:函式宣告一定要是具名函式。

var

foo=

function () {}settimeout( function

foo() {} )-

function

foo() {}();

立即執行函式(iife)
vara=2;

(function

foo() )();

console.log( a ); // 2

函式名對 iife 當然不是必須的,iife 最常見的用法是使用乙個匿名函式表示式。雖然使 用具名函式的 iife 並不常見,但它具有以下優勢:

匿名函式在棧追蹤中不會顯示出有意義的函式名,使得除錯很困難。

如果沒有函式名,當函式需要引用自身時只能使用已經過期的arguments.callee引用, 比如在遞迴中。另乙個函式需要引用自身的例子,是在事件觸發後事件***需要解綁 自身。

匿名函式省略了對於**可讀性/可理解性很重要的函式名。乙個描述性的名稱可以讓 **不言自明。

因此具名函式的 iife 也是乙個值得推廣的實踐。

(function() {}())
這也是iife的一種表達方式,功能上和上面那種方式是一致的。選擇哪種全憑個人愛好。

iife 也可以和其他形式的函式一樣實現引數的傳遞(多說一句:引數傳遞是按值傳遞)。

(function

foo(a) )(3);

這個模式的另外乙個應用場景是解決 undefined 識別符號的預設值被錯誤覆蓋導致的異常(雖 然不常見)。將乙個引數命名為 undefined,但是在對應的位置不傳入任何值,這樣就可以 保證在**塊中 undefined 識別符號的值真的是 undefined:

undefined

=true; // 給其他**挖了乙個大坑!絕對不要這樣做!

(function

iife( undefined ) })();

iife 還有一種變化的用途是倒置**的執行順序,將需要執行的函式放在第二位,在 iife 執行之後當作引數傳遞進去。儘管這種模式略顯冗長,但有些人認為它更易理解。

js之作用域

1.什麼是作用域 作用域是用於收集儲存維護變數,以及當前執行 宣告的變數所擁有的許可權,例如 function foo a foo1 666 function foo2 a g a 在foo2函式中 a向g賦值 此時g在foo2作用域中也不存在,他也向上查詢,遇到window物件,發現其中也沒有定義...

JS之作用域精解

一。執行期上下文 當函式執行時,會建立乙個成為執行期上下文的內部物件。乙個執行期上下文定義了乙個函式執行時的環境,函式每次執行時對應的執行期上下文都是獨一無二的,所以多次呼叫乙個函式會建立多個執行期上下文。每當函式執行完畢,它所產生的執行期上下文被銷毀。即 函式執行時才會產生自己的ao,執行結束後立...

python之作用域

跟很多程式語言一樣,python中也有作用域的使用 函式和變數分有公開的以及非公開的 正常的函式和變數名是公開的 public 比如abc,x123,pi 類似 這樣的變數是特殊變數,可以被直接引用,但是有特殊用途,我們自己的變數一般不用這種變數名 類似 和 的函式和變數就是非公開的private,...