您的位置:首页 > Web前端 > JavaScript

javascript高级程序设计笔记-第七章(函数表达式)

2016-03-02 17:16 573 查看

一、递归

递归函数是在一个函数通过名字调用自身的情况下构成的

function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * factorial(num-1);
}
}

但是将此函数赋值给另一个函数时会出错

var anotherFactorial = factorial;
factorial = null;
alert(anotherFactorial(4));     //报错

使用arguments.callee

function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * arguments.callee(num-1);
}
}
var anotherFactorial = factorial;
factorial = null;
alert(anotherFactorial(4));     //24

但是arguments.callee在严格模式下会导致错误

所以严格模式下,使用命名函数表达式

var factorial = (function f(num) {
if (num <= 1) {
return 1;
} else {
return num * f(num-1);
}
});
//创建一个名为f()的命名函数表达式,然后将其赋值给变量factorial

二、闭包

闭包是有权访问另一个函数作用域中的变量的函数,通常是通过在一个函数内部创建另一个函数来创建闭包

function compare(value1, value2) {
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
return 1;
} else {
return 0;
}
}
var result = compare(5, 10);

下图是compare()函数执行时的作用域链



一般当函数执行完毕后,局部活动对象就会被销毁,但是闭包不是,当creatComparisonFunction()函数返回后,其执行环境的作用域链会被销毁,但是它的活动对象仍然会留在内存中;直到匿名函数被销毁后,它的活动对象才会被销毁

function creatComparisonFunction(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 compareNames = creatComparisonFunction("name");
//调用函数
var result = compareNames({name: "Nicholas"}, {name: "Greg"});




1、闭包与变量

副作用:闭包只能取得包含函数中任何变量的最后一个值

function createFunctions() {
var result = new Array();
for (var i = 0; i < 10; i++) {
result[i] = function() {
return i;
};
}
return result;
}

这个函数会返回一个数组,表面上看,似乎每个函数都应该返回自己的索引值,实际上每个函数都返回10

可以定义一个匿名函数,并将立即执行该匿名函数的结果赋值给数组。而在这个匿名函数内部,创建一个闭包

function createFunctions() {
var result = new Array();
for (var i = 0; i < 10; i++) {
result[i] = function(num) {
return function() {
return num;
};
}(i);
}
return result;
}

2、关于this对象

在全局函数中,this等于window,当函数被作为某个对象的方法调用时,this等于那个对象。

匿名函数的执行环境具有全局性,其this通常指向window。

var name = "the window";
var object = {
name: "my object",
getNameFunc: function() {
return function() {
return this.name;
};
}
};
alert(object.getNameFunc()());      //the window

把外部作用域中的this对象保存在一个闭包能够访问到的变量里,就可以让闭包访问该对象

var name = "the window";
var object = {
name: "my object",
getNameFunc: function() {
var that = this;
return function() {
return that.name;
};
}
};
alert(object.getNameFunc()());      //my object

三、模仿块级作用域(私有作用域)

(function() {
//这里是块级作用域
})();

将函数声明包含在一对圆括号中,表示它实际上是一个函数表达式,紧随其后的另一对圆括号会立即调用这个函数

function() {
//这里是块级作用域
}();    //报错
//函数声明后面不能跟圆括号,而函数表达式后面可以跟圆括号

如果只是临时需要一些变量,就可以使用私有作用域

function outputNumbers() {
(function() {
for (var i = 0; i < 10; i++) {
console.log(i);     //0,1,2,3,4,5,6,7,8,9
}
})();
console.log(i);     //报错
}
outputNumbers();

这种技术通常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数

四、私有变量

任何在函数中定义的变量,都可以认为是私有变量。私有变量包括函数的参数、局部变量和函数内部定义的其他函数

特权方法:有权访问私有变量和私有函数的共有方法

方法是在构造函数中定义特权方法

function MyObject() {
var privateVariable = 10;
function privateFunction() {
return false;
}
//特权方法
this.publicMethod = function() {
privateVariable ++;
return privateFunction();
};
}
//变量privateVariable和函数privateFunction()只能通过特权方法publicMethod()来访问

可以利用私有和特权成员,隐藏那些不应该被直接修改的数据

function Person(name) {
this.getName = function() {
return name;
};
this.setName = function(value) {
name = value;
};
}
var person = new Person("Nicholas");
alert(person.getName());        //Nicholas
person.setName("Greg");
alert(person.getName());        //Greg

1、静态私有变量

(function MyObject() {
//私有变量和私有函数
var privateVariable = 10;
function privateFunction() {
return false;
}
//构造函数
MyObject = function() {};
//特权方法
MyObject.prototype.publicMethod = function() {
privateVariable ++;
return privateFunction();
};
})();

2、模块模式

为单例创建私有变量和特权方法,单例指只有一个实例的对象

var singleton = function() {
//私有变量和函数
var var privateVariable = 10;
function privateFunction() {
return false;
}
//特权方法和属性
return {
publicProperty: true,
publicMethod: function() {
privateVariable ++;
return privateFunction();
}
};
}();

如果必须创建一个对象并以某些数据对其进行初始化,同时还要公开一些能够访问这些私有数据的方法,就可以使用模块模式

3、增强的模块模式

适合那些单例必须是某种类型的实例,同时还必须添加某些属性和方法对其加以增强的情况

var singleton = function() {
//私有变量和函数
var var privateVariable = 10;
function privateFunction() {
return false;
}
//创建对象
var object = new CustomType();
//添加特权方法和属性
object.publicProperty = true;
object.publicMethod = function() {
privateVariable ++;
return privateFunction();
};
//返回这个对象
return object;
}();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: