JS的變數 原型與原型鏈 作用域 閉包
阿新 • • 發佈:2018-12-04
js中的變數型別(按儲存方式區分)
- 值型別
- 引用型別(指標):陣列、函式、物件
//共享記憶體,資料改變存在聯動性。
//可以隨意的擴充套件屬性
在javascript中,判斷資料型別主要依賴下面兩種方式:
- 如果值應為一個引用型別,使用 instanceof 操作符檢查其建構函式;
- 如果值應為一個基本型別,使用 typeof 檢查其型別
type of 函式
typeof只能區分值型別的詳細型別,無法區分引用型別,但可以區分出函式來
typeof undefined;//undefined
typeof 'abc';//string
typeof 123;//number
typeof true;//boolean
typeof {};//object
typeof [];//object
typeof null;//object
typeof console.log//function
===與==
if (obj.a == null){
// 這裡相當於 obj.a === null || obj.a ===undefined ,因為 undefined == null 值為true
// 其他情況最好都用===
}
原型
對於引用型別來說
//都有__proto__屬性,指向其建構函式的 prototype 屬性值
//所有的函式,都有一個 prototype 屬性,屬性值也是一個普通的物件
//函式的 prototype 稱顯式原型,引用型別的 _proto 成為隱式原型
//
原型是一個物件,其他物件可以通過它實現屬性繼承。
原型鏈:
所有的引用型別(陣列,物件,函式), __proto__屬性(隱式原型)指向它的建構函式的“prototype”屬性值(顯式原型)
執行上下文
在程式碼執行之前,先執行(解析)變數定義和函式宣告。
範圍:一段<script>
或者一個函式之內都會生成一個上下文
全域性:變數定義,函式宣告.執行之前,一段<script>
會生成全域性上下文
函式:變數定義,函式宣告,this,arguments.函式執行之前會生成函式上下文
函式宣告
function fn(name) {
...
}
函式表示式
var func = function () {
...
}
this
this要在執行時才能確認值,定義時無法確認
使用場景
- 作為建構函式執行
- 作為物件屬性執行
- 作為普通函式執行
作用域鏈
函式的父級作用域是函式定義時候的作用域,不是函式執行時候的作用域,也就是說那個作用域定義了這個函式,這個函式的父級作用域就是誰,跟函式執行沒有關係,函式自由變數要到父級作用域中找,就形成了作用域鏈
閉包
閉包使用場景
- 函式作為返回值
- 函式作為引數傳遞
(函式自由變數要到父級作用域(定義時的作用域)中找)
閉包在實際中的應用
在函式外無法修改函式內的值
function isFirstLoad(){
var _list = []
return function(id) {
//函式作用域
if(_list.indexOf(id) >= 0) {
return false
} else {
_list.push(id)
return true
}
}
}
var firstLoad = isFirstLoad()
firstLoad(1) //true
firstLoad(1) //false
firstLoad(10) //true
firstLoad(10) //false
//對於這個程式來說,在isFirstLoad函式外面,無法修改_list的值
問題:建立10個<a>
標籤,點選的時候彈出來對應的序號
錯誤方法
var i,a
for(i = 0; i < 10; i++) {
a = document.createElement('a')
a.innerHTML = i + '<br>'
a.addEventListener('click', function(e) {
//點選時執行
e.preventDefault()
alert(i) //自由變數,要去父作用域(全域性作用域)尋找
})
document.body.appendChild(a)
在執行時,當click事件發生時,外層for迴圈已經執行完畢,即i已經加到10了。
所以無論點選哪個元素,彈出來的序號都是10.
正確方法
var i
for(i=0;i<10;i++) {
(function(i) {
//函式作用域
//自執行函式,不用呼叫,只要定義完成,就會立即執行。
var a = document.createElement('a');
a.innerHTML = i + '<br>'
a.addEventListener('click',function(e) {
e.preventDefault()
alert(i)
//改變了父級作用域
})
document.body.appendChild(a)
})(i)//相當於建立了10個函式,每個函式都帶著從0-9的i作為引數
}