在【函數定義】的時候,【函數對象】的【scope屬性】便會引用包含該函數的上一級函數在運行時所生成的【執行上下文】的【活動對象】,由於發生對象屬性之間的相互依賴,致使包含此函數的【scope屬性】所指向的活動變量,在上一級函數【執行完畢】將要【釋放執行上下文】的時候【不能釋放】其包含的【活動變量】。瀏覽器
本身的理解: 閉包的產生首先要有一個地址被引用所指向閉包
在一段js代碼執行前,瀏覽器已經作了一些準備工做,其中包括對變量的聲明,變量賦值是在賦值語句執行的時候進行的。app
函數每被調用一次,都會產生一個新的執行上下文環境,由於不一樣的調用可能會有不一樣的參數。 函數定義的時候就應經肯定了函數體內部變量的做用域
執行全局代碼時,會產生一個全局上下文環境,每次調用函數,又會產生函數上下文環境,當函數調用完成時,這個上下文環境及其中的數據都會被銷燬。再從新回到全局上下文環境。函數
處於活動狀態的執行上下文環境只有一個。(壓棧和出棧的過程)this
除全局做用域以外,每一個函數都會建立本身做用域。做用域在函數定義時就已經肯定了,而不是在調用時肯定。 做用域只是一個「地盤」,一個抽象的概念,其中沒有變量,要經過做用域對應的執行上下文來獲取變量的值,同一做用域下,不一樣的調用會產生不一樣的執行上下文環境,繼而產生不一樣的值。prototype
在一個做用域中使用的變量,沒有在其中聲明(即在其餘做用域中聲明的),此時,這個變量對這個做用域來說就是自由變量(也可稱爲活動變量)code
對象冒充對象
function Person(name, age) { this.name = name; this.age = age; this.sayName = function() { console.log(this.name); }; } function Student(name, age) { this.obj = Person; this.obj(name, age); delete this.obj; this.study = function() { console.log("study"); } } var stu1 = new Student("zhangsan", 21); console.log(stu1.name, stu1.age); stu1.sayName(); stu1.study();
原型鏈的方式繼承
function Person(name, age) { this.name = name; this.age = age; this.sayName = function () { console.log(this.name); }; } function Student(name, age) { this.constructor(name, age); } Student.prototype = new Person(); var stu1 = new Student("zhangsan", 21); console.log(stu1.name, stu1.age);
call和apply方法內存
function Student(name, age) { // Person.call(this, name, age); Person.apply(this, [name, age]); } var stu = new Student("zhangsan", 21); console.log(stu.name, stu.age);
混合方式
function Person(name, age) { this.name = name; this.age = age; } Person.prototype.sayName = function() { console.log(this.name); }; function Student(name, age) { Person.call(this, name, age); } Student.prototype = new Person();