1. 程式人生 > >JS的變數 原型與原型鏈 作用域 閉包

JS的變數 原型與原型鏈 作用域 閉包

js中的變數型別(按儲存方式區分)

  1. 值型別
  2. 引用型別(指標):陣列、函式、物件
    //共享記憶體,資料改變存在聯動性。
    //可以隨意的擴充套件屬性

在javascript中,判斷資料型別主要依賴下面兩種方式:

  1. 如果值應為一個引用型別,使用 instanceof 操作符檢查其建構函式;
  2. 如果值應為一個基本型別,使用 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 成為隱式原型
//
原型是一個物件,其他物件可以通過它實現屬性繼承。
image


image
image
原型鏈:
所有的引用型別(陣列,物件,函式), __proto__屬性(隱式原型)指向它的建構函式的“prototype”屬性值(顯式原型)


執行上下文

在程式碼執行之前,先執行(解析)變數定義和函式宣告。

範圍:一段<script>或者一個函式之內都會生成一個上下文
全域性:變數定義,函式宣告.執行之前,一段<script>會生成全域性上下文
函式:變數定義,函式宣告,this,arguments.函式執行之前會生成函式上下文

函式宣告

function fn(name) {
    ...
}

函式表示式

var func =
function () { ... }

this

this要在執行時才能確認值,定義時無法確認

使用場景

  1. 作為建構函式執行
  2. 作為物件屬性執行
  3. 作為普通函式執行

作用域鏈

函式的父級作用域是函式定義時候的作用域,不是函式執行時候的作用域,也就是說那個作用域定義了這個函式,這個函式的父級作用域就是誰,跟函式執行沒有關係,函式自由變數要到父級作用域中找,就形成了作用域鏈

閉包

閉包使用場景

  1. 函式作為返回值
  2. 函式作為引數傳遞
    (函式自由變數要到父級作用域(定義時的作用域)中找)

閉包在實際中的應用

在函式外無法修改函式內的值

    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作為引數
    }