一、什么是閉包?
閉包就是有權訪問其他函式作用域中的變數的函式
1. 閉包的原理:
用我自己的話說:當我們定義一個函式時,需要訪問函式內部的變數是訪問不到的,所以需要在函式內部定義一個匿名函式并return 出去,這樣就可以在函式外部訪問了
2. 作用域鏈
首先,后臺的執行環境都有一個表示變數的物件 – 變數物件。全域環境的變數物件始終存在,而函式內部中區域環境的變數物件,則只在函式執行程序中存在
在創建函式時,會先創建一個預包含全域變數物件的作用域鏈(指向變數物件的指標),這個作用域鏈保存在內部scope屬性中
呼叫這個函式時,會為這個函式創建一個執行環境,然后通過復制函式內部scope 屬性中的物件構建執行環境的作用域鏈
會在該函式執行環境作用域前端創建一個活動物件(0 活動物件,1 全域物件)
在函式內部定義的匿名函式會將外部函式的活動物件添加到他的作用域中
當內部函式回傳后,內部匿名函式的作用域鏈被初始化為包含外部函式的活動物件和全域變數物件,這樣內部匿名函式就可以訪問外部函式的所有變數
注意
外部函式執行完后,活動物件也不會被銷毀,因為內部函式的作用域鏈仍然在參考這個活動物件
當外部函式被回傳后,他的作用域鏈會被銷毀,但是他的活動物件依然被保存在記憶體中,直到內部匿名函式被銷毀,外部函式的活動物件才會被銷毀。
3. 創建常見閉包的方式
在一個函式內部創建一個匿名函式
function out() { var num = 1; return function (n){ return (n + num) } } var a = out() console.log(a(1)) console.log(out()(2)
4. 閉包中的this指向問題
this 是在運行時基于函式的執行環境系結的
在全域函式中,this等于window
當函式被某個物件的方法呼叫時,this等于那個物件
每個函式在呼叫時都會自動取得兩個特殊變數:this 和 arguments,內部函式在搜索這兩個變數時,只會搜索到其活動物件為止,因此不可能訪問到外部函式的這兩個變數
解決辦法
把外部函式作用域中的this 物件保存在一個閉包能訪問到的變數里,就可以讓閉包訪問該物件了。
var name="welkin" var obj = { name : "zhangsan", getName: function(){ return function(){ return this.name } } } console.log(obj.getName()()) //welkin
使用變數儲存this:
var name="welkin" var obj = { name : "zhangsan", getName: function(){ var that = this; return function(){ return that.name } } } console.log(obj.getName()())
三、如何實作繼承
1. 實作繼承的基本思想
在js中我們使用實作繼承(繼承實際的方法)基于原型鏈進行繼承
利用原型讓一個參考型別繼承另一個參考型別的屬性和方法
2. 原型鏈
每個建構式都有一個原型物件(原型物件有一個指向建構式的指標)
每個實體都有一個指向原型物件的內部指標
將原型物件等于另一個型別的實體
此時的原型物件將包含著指向另一個原型的指標,另一個原型也包含著指向另一個建構式的指標。
3. 原型系統
如果所有的物件都有私有欄位(prototype),就是物件的原型
讀取屬性時,如果物件本身沒有,則會繼續訪問物件的原型,直到原型為慷訓是找到為止
4. 操作原型的方法
Object.create根據指定的原型創建新物件,原型可以是null
Object.getPrototypeOf 獲得一個物件的原型
Object.setPrototypeOf 設定一個物件的原型
5. 默認的原型(陣列方法是哪來的?)
所有的參考型別默認都繼承了object
所有函式的默認原型都是object的實體,因此默認原型都會包含一個內部指標,指向object.porototype
這也是所有的自定義型別都會繼承toString() valueOf() 的根本原因
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/91919.html
標籤:基礎類
