js閉包、原型、繼承、做用域

做用域:javascript

做用域是針對變量而言的,好比定義了一個函數啊a1,a1裏面又定義一個子函數a2,此時就會有三個做用域  全局做用域--a1做用域--a2做用域java

當a2查找變量時會先從自身的做用域開始查找,找不到就向上一級做用域a1查找,直到全局做用域,這就造成了一個做用域鏈react

原型:設計模式

javascript中,一切皆對象,每一個對象都會會有一個_propo_屬性(瀏覽器自動建立),該屬性指向它的原型,當一個對象查詢一個屬性的時候,自身沒有就會根據_propo_向原型查找,直到object.prototype._propo_爲null,這樣就造成了一個原型鏈瀏覽器

prototype是什麼呢?閉包

咱們直到咱們能夠經過一個構造函數建立一個類,prototype的做用就是讓類的屬性能夠被繼承,因此只有構造函數纔有prototype這個屬性app

繼承:函數

javascript中的繼承是經過原型鏈來體現的。先看幾句代碼學習

以上代碼中,f1是Foo函數new出來的對象,f1.a是f1對象的基本屬性,f1.b是怎麼來的呢?——從Foo.prototype得來,由於f1.__proto__指向的是Foo.prototypethis

訪問一個對象的屬性時,先在基本屬性中查找,若是沒有,再沿着__proto__這條鏈向上找,這就是原型鏈

那麼咱們在實際應用中如何區分一個屬性究竟是基本的仍是從原型中找到的呢?你們可能都知道答案了——hasOwnProperty,特別是在for…in…循環中,必定要注意。

 

等等,不對! f1的這個hasOwnProperty方法是從哪裏來的? f1自己沒有,Foo.prototype中也沒有,哪兒來的?

好問題。

它是從Object.prototype中來的,請看圖:

對象的原型鏈是沿着__proto__這條線走的,所以在查找f1.hasOwnProperty屬性時,就會順着原型鏈一直查找到Object.prototype。

 

因爲全部的對象的原型鏈都會找到Object.prototype,所以全部的對象都會有Object.prototype的方法。這就是所謂的「繼承」。

固然這只是一個例子,你能夠自定義函數和對象來實現本身的繼承。

 

說一個函數的例子吧。

咱們都知道每一個函數都有call,apply方法,都有length,arguments,caller等屬性。爲何每一個函數都有?這確定是「繼承」的。函數由Function函數建立,所以繼承的Function.prototype中的方法。不信能夠請微軟的Visual Studio老師給咱們驗證一下:

看到了吧,有call、length等這些屬性。

那怎麼還有hasOwnProperty呢?——那是Function.prototype繼承自Object.prototype的方法。有疑問能夠看看上一節將instanceof時候那個大圖,看看Function.prototype.__proto__是否指向Object.prototype。

 

原型、原型鏈,你們都明白了嗎?

 

 

JavaScript 閉包與類(原型鏈)之間的開發方式?

最近遇到一個問題.關於如何利用閉包開發與如何利用原型鏈開發.
本身看了一本書《JavaScript設計模式與開發實踐》 裏面有一章提到了高階函數.並且在這本書不少設計模式都能利用閉包來實現.等等之類的.
本身在學習的過程當中也一直不明白類(原型鏈)的開發與閉包的開發
好比用構造函數寫個類
function Girl(name){
this.name=name
}
Girl.prototype.sayname=function(){console.log(this.name)}
這也能夠用閉包來實現
var Girl=function(name){
var girlname=name;
var sayname=function(){
console.log(name)
}
return {
sayname:sayname
}
}
那麼問題來了。

如何利用閉包來編寫程序和如何利用原型鏈來編寫程序,這兩種編寫模式有什麼差異。如何寫纔是最佳的方式。在什麼狀況下使用原型鏈模式來編寫?什麼狀況下使用閉包來編寫?

這是個很寬泛的問題,利用閉包和原型能幹什麼事情。我從你題中的應用場景,分析下用原型和用閉包實現的不一樣點。
案例1:
function Girl(name){
this.name=name
}
Girl.prototype.sayname=function(){console.log(this.name)}
var a = new Girl('Lucy');
var b = new Girl('Lily');
案例2:
var Girl=function(name){
var sayname=function(){
console.log(name)
}
return {
sayname:sayname
}
}
var a = Girl('Lucy');
var b = Girl('Lily');
案例1中,a,b的結構以下圖所示(一些無關的屬性沒有徹底畫出):


案例2中,a,b的結構以下圖所示(一些無關的屬性沒有徹底畫出):

咱們來對比下二者的區別以及緣由:
1. 方案1中:構造出來的對象a、b,經過原型共享sayname方法;方案2中生成的對象a、b各有本身的屬性方法sayname(空間上浪費)。這就是原型設計的初衷。咱們經過這裏也看到了自身屬性和原型屬性的區別(順便說下能夠經過hasOwnProperty屬性來區分)。
2. 方案1中:構造出來的對象a、b各有本身的屬性name,咱們能夠經過a.name,b.name來訪問這個屬性;方案2中,生成的對象a、b並無屬性name,而他們的方法屬性sayname的做用域鏈上有name變量,在sayname方法裏面能夠訪問name變量。咱們看到方案1中的name屬性具備面向對象中的公有屬性的特性,而方案二中name具備面向對象中的私有屬性的特性。

 

關於閉包,我在內網論壇寫過一篇文章,有童鞋轉載到csdn JS閉包 - JokerWILL ,有興趣能夠看下。

因此咱們要了解原型和閉包的特性,瞭解使用原型和閉包會產生怎樣不一樣的結果,根據咱們的需求來靈活的使用。

題主這問題問得....
原型鏈是幹什麼用的,是共享屬性和方法,是能夠實現繼承的
閉包是對變量和方法的封裝,能夠延遲使用外部變量和方法

構造函數上的方法是每一個實例對象都有這個方法,彼此不一樣

原型鏈的方法是各個實例對象共享這個方法

首先明白概念是什麼,可以幹什麼用,再說什麼模式一類的東西,模式是大量實踐總結出來的通用作法,js高級程序設計,必定多看幾遍
相關文章
相關標籤/搜索