ES5中的函数

1.在ES5中函数定义有两种方式:

函数声明: function functionName(arg){}

函数表达式:var functionName = function(arg){}

这两种方式定义的函数都可以使用,但是他们还是有一些区别的

1.函数声明方式定义的函数,会有函数声明提升的,即你可以在函数声明之前调用改函数,而函数表达式定义的函数不可以

2.匿名函数,匿名函数顾名思义就是其函数没有方法名字

function createCompareFunction(property){

return function (obj1,obj2){

var value1 = obj1[property];

var value2 = obj2[property];

if (value1 < value2){

return -1;

}else if (value1 > value2){

return 1;

}else{

return 0;

}

}

}

如上代码所示,createCompareFunction就会返回一个匿名函数

3 es5中的递归函数,可以使用arguments.callee(这个指向了当前正在执行的函数)来实现,避免函数表达式被赋值为其他,也可以使用命名函数表达式的方法

var factor = (function f (num){

if (num <=1){

return 1;

}else{

return num * f(num-1);

}

});

4.函数自执行

(function (name){

console.log(name);

}('xindi'));

如下实现,这个匿名函数会马上执行

5.闭包

闭包是指能有权访问另一个函数作用域中的变量的函数.

闭包在执行的时候,会使用arguments和其他的命名参数创建自己的活动对象,闭包的作用域链中会包含外部函数的活动对象,当在函数中访问一个变量时,就会从其作用域链中搜索直到找到为止.所以这就是闭包为什么可以访问其外部函数的变量.

ps:this对象和arguments对象只会搜索自己的活动对象,不会去访问外部函数的活动对象.

但是闭包作用域链中保存的是整个的活动对象,而不是某个特殊的变量,所以当闭包执行之后你可能得到的并不是你想要的结果,例如

function createFunctions (){

var newArr = new Array();

for (var i = 0;i<10;i++) {

newArr[i] = function (){

return i

}

}

return newArr;

}

createFunctions().map(function(item){

let result = item();

console.log(result);

});

这个例子中item就是闭包,每个item都都包含了createFunctions的活动对象,但其实每个item引用的都是同一个活动对象.当createFunctions执行完毕之后createFunctions内部的变量I值为10,此时item(闭包)包含的活动对象中I的值也是10.所以得到的结果会都是10;

当然我们也可以采用其他的方式来避免这种情况,如果一定要使用闭包的话,可以采取下面的方式:

function createFunctions (){

var newArr = new Array();

for (var i = 0;i<10;i++) {

newArr[i] = function (num){

return function(){

return num;

}

}(i)

}

return newArr;

}

createFunctions().map(function(item){

let result = item();

console.log(result);

});

这个方式我们采取自执行函数,让闭包返回的变量i的副本.

在闭包中我们还需要关注另一个问题就是this对象和arguments对象.this和arguments对象只会在本身的活动对象去寻找,所以当有闭包的时候,闭包内部访问的this和arguments对象可能不是你想要的.

我们可以有以下几种解决方案:

1.将this和arguments对象用另一个变量保存下来,在闭包内部访问你保存的那个对象

2.借用bind函数,创建一个this对象为你传入的新函数.

3.借用call 或 apply 改变闭包内部的执行环境

6.es5中模仿块级作用域的变量,在es6中,实现let 和const两个块级作用域的变量,但是在es5中只有var,var声明的作用域是非块级的.不过我们可以使用闭包来模仿此行为

(function(){

var i = 0;

}())

如上所示,我们声明了一个匿名的自执行函数,这样在这个函数内部的变量都会只在此函数内部生效,类似块级的变量.

7.私有变量,严格意义上来说在js中并不存在私有变量,但是我们可以通过不同的方式来实现类似私有变量

1.特权方法:

function Person(){

var priviteVar = 10;

function privateFunc (){

console.log(priviteVar);

return 'lsh';

}

this.publicFunc = function(){

priviteVar += 1;

return privateFunc();

}

}

这样实现的结果就是priviteVar 和privateFunc都只能通过publicFunc来访问

2.静态私有变量:

(function(){

var priviteVar = 10;

function privateFunc(){

priviteVar += 1;

return 'lsh'+priviteVar;

}

Person = function (name){

this.name = name;

}

Person.prototype.publicFunc = function (){

return privateFunc();

}

}())

上面的实现,构造函数和priviteVar都处于同一个函数环境下,这样priviteVar就会成为一个静态变量,也就是你调用构造函数创建多个对象,其仍然共享同一个priviteVar.

8.模块模式

有时候程序中我们会需要一个单利对象来管理程序的一些信息,同时这个单利对象我们可能需要有它的私有变量,那么我们可以使用模块模式来实现

var single = function (){

var privateVar = 10;

function privateFunc (){

return 'lsh';

}

var obj = new Object();

obj.publicProperty = false;

obj.publicFunc = function (){

privateVar += 1;

return privateFunc();

}

return obj;

}

这样我们可以得到一个单利对象,同时这个对象有自己的私有方法和属性,也有着公有方法和属性;

你可能感兴趣的:(ES5中的函数)