var sayHi; var a=1; if (a>0) { sayHi=function(){ console.log("Hi"); } } else{ sayHi=function(){ console.log("Yo"); } } sayHi();
function createComparisonFunction(propertyName) { return function(object1,object2){ var value1=object1[propertyName]; var value2=object2[propertyName]; if (value1<value2) { return -1; } else if (value1>value2) { return 1; } else{ return 0; } } } var data=[{name:"Zachary",age:28},{name:"Nicholas",age:29}]; data.sort(createComparisonFunction("name")); console.log(data[0].name);//"Nicholas" data.sort(createComparisonFunction("age")); console.log(data[0].name);//"Zachary"
function factorial(num) { if (num<=1) { return 1; } else{ return num*arguments.callee(num-1); } } console.log(factorial(5));
arguments.callee是一個指向正在執行的函數的指針javascript
使用arguments.callee而非原函數名factorial能夠解決以下報錯問題:java
var anotherFactorial=factorial; factorial=null; anotherFactorial(5);
問題:不能在嚴格模式下訪問arguments.callee閉包
var factorial=(function f(num){ if(num<=1){ return 1; } else{ return num*f(num-1); } }) console.log(factorial(5));
閉包指有權訪問另外一個函數做用域中變量的函數。函數
閉包的常見形式是在一個函數內部建立另外一個函數。this
由於閉包會攜帶包含它的函數的做用域,所以會比其餘函數佔用更多的內存。過分使用閉包可能致使內存佔用過多,故建議只在絕對須要閉包的時候再考慮用閉包。prototype
對比如下代碼1和代碼2:設計
代碼1:指針
var name="The window"; var object={ name:"My Object", getNameFunc:function(){ return function(){ return this.name; } } } console.log(object.getNameFunc()());//"The window"
代碼2:code
var name="The window"; var object={ name:"My Object", getNameFunc:function(){ return this.name; } } console.log(object.getNameFunc());//"My Object"
緣由:對象
匿名函數的執行環境具備全局性。爲何匿名函數沒有取得其包含做用域的this對象呢?由於做用域鏈的原理,內部匿名函數在搜索this和arguments兩個特殊變量是都是從自身的活動對象開始,在搜索外部函數的活動對象,所以不可能直接訪問外不函數的這兩個變量;而其自身的this是指向全局環境的。
下面那個不是匿名函數,是函數getNameFunc()。能夠姑且這麼理解吧??
能夠把外部做用域的this用其餘變量來保存,這樣內部閉包能夠經過訪問這個變量來訪問外部做用域的this:
var name="The window"; var object={ name:"My Object", getNameFunc:function(){ var that=this; return function(){ return that.name; }; } } console.log(object.getNameFunc()());//"My Object"
P183,待整理
function outputNumbers(count) { for (var i=0;i<count;i++) { console.log(i); } var i; console.log(i); } outputNumbers(10);//0 1 2 3 4 5 6 8 8 9 10
即便屢次聲明一個變量,JS會忽略後續的聲明(不過,它會執行後續聲明中的變量初始化)。
用做塊級做用域(又叫私有做用域)的匿名函數語法以下:
(IIFE,(Immediately-Invoked Function Expression),當即執行的函數表達式)
function outputNumbers(count) { (function(){ for (var i=0;i<count;i++) { console.log(i); } })(); console.log(i);//(1) } outputNumbers(10);//0 1 2 3 4 5 6 7 8 9 報錯(語句(1)錯誤)
任何在函數中定義的變量,均可以認爲是私有變量。由於不能在函數外訪問。
私有變量包括函數的參數、局部變量、函數內部定義的其餘函數
有權訪問私有變量和私有函數的方法叫作特權方法。
建立這樣的公有方法的思想是:在函數內部建立一個閉包,利用閉包能夠經過本身的做用域鏈訪問這些變量。
在構造函數中定義特權方法。
例一:
function MyObject() { var privateVariable=20;//私有變量 function privateFunction() {//私有函數 return false; } this.publicMethod=function(){//特權方法 privateVariable++; return privateFunction(); }; } var object=new MyObject() console.log(object.publicMethod());//false
例二:
function Person(name) {//參數爲私有變量 this.getName=function(){//特權方法 return name; } this.setName=function(newName){//特權方法 name=newName; } } var aperson=new Person("Tom"); console.log(aperson.getName());//Tom aperson.setName("Ben"); console.log(aperson.getName());//Ben
經過在私有做用域中定義私有變量和函數,也能夠建立特權方法。
(function () { var privateVariable=20;//私有變量 function privateFunction() {//私有函數 return false; } MyObject=function(){//構造函數,沒有var聲明就是全局變量 }; MyObject.prototype.publicMethod=function(){//公有/特權方法 privateVariable++; return privateFunction(); } })(); var object=new MyObject(); console.log(object.publicMethod());//false
該模式私有變量和函數是由實例共享的,因爲原型方法是在原型上定義的,故全部實例都引用同一個函數(以下例)。而特權方法做爲一個閉包保存着對包含做用域的引用。
(function(){ var name=""; Person=function(value){ name=value; }; Person.prototype.getName=function(){ return name; }; Person.prototype.setName=function(value){ name=value; }; })(); var person1=new Person("Nicholas"); console.log(person1.getName());//"Nicholas" person1.setName("Greg"); console.log(person1.getName());//"Greg" var person2=new Person("Michael"); console.log(person1.getName());//"Michael" console.log(person2.getName());//"Michael"
做用:是爲單例建立私有變量和特權方法。
單例:只有一個實例的對象。
方式:在匿名函數內部,首先定義私有變量和函數,而後將一個對象字面量做爲匿名函數的返回值。返回的對象字面量裏面只包括能夠公開的屬性和方法。該對象是在匿名函數內部定義的,故它的公有方法有權訪問私有變量和函數。
var singleton=function(){ var privateVariable=10;//私有變量 function privateFunction() {//私有函數 return false; } return { publicProperty:true,//特權/公有屬性 publicMethod:function(){//特權/公有方法 privateVariable++; return privateFunction(); } }; }();
適用:若是必須建立一個對象並以一些數據對其進行初始化,同時還要公開一些可以訪問這些私有數據的方法,就可使用模塊模式。
對模塊模式的改進,即在返回對象以前加入對其加強的代碼。
適用於:單例必須是某種類型的實例,同時還必須添加某些屬性和方法對其加強的狀況。
var singleton=function(){ var privateVariable=10;//私有變量 function privateFunction() {//私有函數 return false; } var object=new CustomType();//建立對象 object.publicProperty=true; object.publicMethod=function(){ privateVariable++; return privateFunction(); } return object; }();