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; }();