摘要:獲取返回的匿名函數這個匿名函數會保留原本的作用域鏈有意思的是函數參數也是可以被我們捕獲到的這就給我們靈活的創造一些函數提供了便利,比如我們需要創造一個函數工廠,這個工廠可以根據我們提供的參數生產出不同的函數。
關于this的討論本文是在看《Javascript函數式》編程一書寫下的一些記錄。和大家分享。不足之處還望大家指正。
首先來看這么幾段代碼
function globalThis(){return this;} globalThis(); //=>window or global object globalThis.call("haha"); //=>"haha" globalThis.apply("abc",[]); //=>"abc
可以看到,this的一般就是由調用他的對象決定的,如果進行綁定了的話,相當于說這個函數的調用對象只能夠是你綁定的那個對象,是不能夠更改的。
var bindThis = globalThis.bind("abc") bindThis(); //=>"abc" bindThis.call("x") //=>"abc" bindThis.apply("y",[]); //=>"abc
當然,如果我看到這本書推薦大家使用underscore庫。用法如下
_.bind(globalThis,"abc")
這樣的操作也是可以的。如果說有很多個函數都需要綁定到同一個對象上去怎么辦呢?underscore提供了bindAll(obj,methondName)
var buttonView = { label : "underscore", onClick: function(){ alert("clicked: " + this.label); }, onHover: function(){ console.log("hovering: " + this.label); } }; _.bindAll(buttonView, "onClick", "onHover");函數的閉包
相信大家都或多或少踩過閉包這個坑吧,確實一開始接觸感覺很不能理解。我個人粗淺理解是閉包是一個函數執行過后返回一個內部函數,這個內部函數將保留包含這個內部函數的函數的作用域鏈。也就是里面把外面包住了,簡稱閉包2333。
function captureOut(){ var a = 123; return function(){ console.log("a:"+a); } } var getA = captureOut();//獲取captureOut返回的匿名函數 getA();//這個匿名函數會保留原本的作用域鏈 //=>a:123
有意思的是函數參數也是可以被我們捕獲到的
function capturePara(PARA){ return function(){ console.log(PARA); } } var getP = capturePara("I"m the parameters"); getP();//I"m the parameters
這就給我們靈活的創造一些函數提供了便利,比如我們需要創造一個函數工廠,這個工廠可以根據我們提供的參數生產出不同的函數。見下面代碼
function createDivider(divFactor){ return function(num){ return num/divFactor } } var div9 = createDivider(9);//創造一個可以用來除以9的函數 var div3 = createDivider(3);//除以3的 div9(81);//=>9 _.map([9,18,27],div3);//=>[3,6,9]
既然可以訪問函數內部變量,那么自然也可以訪問this咯,可是this是會隨著調用對象不同而變化的,我們可以通過其他名字來保存this
function captureThis(NAME){ this.name = NAME; var that = this; return function(){ return that.name; } } var getThis = captureThis("小花"); getThis.call({}); //=>小花
可以看到,雖然我們重新把getThis綁定到其他地方去了,還是能夠得到我們的“小花”。如果我們再一次利用captureThis()函數來創建一個新的函數,綁定新的值不會影響到原來的“小花”
var getHong = captureThis("小紅"); getHong.call({}); //=>小紅
剛剛我們討論的都是內部變量和外部變量名字不同的情況,如果相同會出現什么現象呢?繼續往下看吧
var name = "大黃"; function captureName(name){ return function(){ return name; } } var getName = captureName("阿狗"); getName();//?
會領養到阿狗還是大黃呢?其實這個還算簡單,返回的閉包就是返回原來的作用域鏈,首先訪問到的當然是最近的name,因此正確答案是“阿狗”(直接拷貝代碼到console就可以測試)
再來看下面的例子
function captureName(name){ return function(name){ return name; } } var getName = captureName("阿黃"); getName("大狗");//=>?
這一次其實也差不多,相同的變量同時存在于外包函數參數和內部匿名函數的參數中,我們還是按照就近原則,最近的當然是內部匿名函數的參數,因此這次拿到的是“大狗”。
注意,只要拿到了閉包的返回函數,即便是修改原來外部的函數也不會對現有接收到的返回函數造成影響。比如說把captureName改為null,那么照樣可以使用getName。
不過下面的代碼可能讓你有些困惑
function showObj(obj){ return function(){ return obj } } var a = 10; var showA = showObj(a); showA();//=>10; a=20; showA();//=>10; var b = {name:"daming"} var showB = showObj(b); showB();//{name:"daming"} b.age =12; showB();//{name:"daming",age:12} b=null; showB();//{name:"daming",age:12}
是不是覺得有點暈,我也有點暈。書上是說,“由于引用對象同時存在于閉包內部和閉包外部,它的變化可以跨越看似私有的界限,很容易導致混亂,所以通常都盡量減少暴露捕獲變量的風險,把捕獲的對象作為私有數據。”
var pingpong = (function(){ var private=0; return{ inc:function(n){ return private+=n; }, dec:function(n){ return private-=n; } } })(); pingpong.inc(3)//=>3
這樣對象是很安全的,甚至可以禁止往閉包里添加函數!
pingpong.showP = function(){return PRIVATE;} pingpong.showP();//notdefined
總結:靈活利用this以及閉包是實現函數式編程的基礎,而正如我們看到的,函數式編程是一種安全而優美的編程方式~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/87968.html
摘要:作用域作用域是指程序源代碼中定義變量的區域。采用詞法作用域,也就是靜態作用域。而與詞法作用域相對的是動態作用域,函數的作用域是在函數調用的時候才決定的。前面我們已經說了,采用的是靜態作用域,所以這個例子的結果是。 JavaScript深入系列的第二篇,JavaScript采用詞法作用域,什么語言采用了動態作用域?兩者的區別又是什么?還有一個略難的思考題,快來看看吧。 作用域 作用域是指...
摘要:在中的應用采用詞法作用域,也就是靜態作用域。那什么又是詞法作用域或者靜態作用域呢請繼續往下看靜態作用域與動態作用域因為采用的是詞法作用域函數的作用域在函數定義的時候就決定了。 開篇 當我們在開始學習任何一門語言的時候,都會接觸到變量的概念,變量的出現其實是為了解決一個問題,為的是存儲某些值,進而,存儲某些值的目的是為了在之后對這個值進行訪問或者修改,正是這種存儲和訪問變量的能力將狀態給...
摘要:靜態作用域指的是一段代碼,在它執行之前就已經確定了它的作用域,簡單來說就是在執行之前就確定了它可以應用哪些地方的作用域變量。 靜態作用域指的是一段代碼,在它執行之前就已經確定了它的作用域,簡單來說就是在執行之前就確定了它可以應用哪些地方的作用域(變量)。 動態作用域–函數的作用域是在函數調用的時候才決定的 JavaScript采用的是詞法作用域即靜態作用域; // 靜態作用域: va...
摘要:中作用域的問題可以說是老生常談,個人認為的作用域中存在著兩種作用域,一種是詞法作用域,一種是動態作用域。但是自動有了箭頭函數后,箭頭函數中的并不是動態作用域,而是屬于詞法作用域,再其定義時就已經確定好了,相當于。 js中作用域的問題可以說是老生常談,個人認為js的作用域中存在著兩種作用域,一種是詞法作用域,一種是動態作用域。 詞法作用域 詞法作用域就是定義在詞法階段的作用域,也就是說由...
摘要:原文原文原文詞法作用域作用域有兩種常見的模型,一種叫做詞法作用域,一種叫做動態作用域。其中詞法作用域更常見,被大多數語言采用,包括。值得注意的是,一個函數作用域只有可能存在于一個父級作用域中,不會同時存在兩個父級作用域。 原文: 原文1 | 原文2 Lexical Scope - 詞法作用域 作用域有兩種常見的模型,一種叫做 詞法作用域 Lexical Scope,一種叫做...
摘要:而閉包的神奇之處正是可以阻止事情的發生。拜所聲明的位置所賜,它擁有涵蓋內部作用域的閉包,使得該作用域能夠一直存活,以供在之后任何時間進行引用。依然持有對該作用域的引用,而這個引用就叫閉包。 引子 先看一個問題,下面兩個代碼片段會輸出什么? // Snippet 1 a = 2; var a; console.log(a); // Snippet 2 console.log(a); v...
閱讀 1433·2021-09-22 15:52
閱讀 1476·2019-08-30 15:44
閱讀 903·2019-08-30 14:24
閱讀 2714·2019-08-30 13:06
閱讀 2709·2019-08-26 13:45
閱讀 2790·2019-08-26 13:43
閱讀 1027·2019-08-26 12:01
閱讀 1450·2019-08-26 11:56