@GivenCui
2016-06-15T09:39:27.000000Z
字数 3634
阅读 923
js高级
- 概念 : 在函数式编程的语言中,闭包的应用广泛. 闭包就是函数内部嵌套另外一个函数(内部函数) , 内部函数引用了外部函数的局部变量,这样就能形成闭包.内部函数中包含了内部函数的代码以及外部函数的局部变量的引用.
- 闭包的最大特点 : 外部函数执行完毕以后, 内部函数对其外部变量的引用, 不会被销毁, 继续存在于内存中. 一般闭包程序的外部函数都会有返回值, 这个返回值是其内部函数. (注意 : 返回值一般都是内部函数)
- 支持闭包的语言具备的特性 :
- 函数可以作为参数进行传递
- 函数可以赋值给变量
- 函数可以作为返回值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>闭包</title>
<script type="text/javascript">
/*
* 思考一个问题 :
* 1. 引用
* 2. 形参
* 3. 指针
*
*/
// 函数嵌套, 就是一个函数内部有另外一个函数
// 立即调用的情况
function fn1 () {
var num = 100; // 通过闭包能把num在外部使用
function subFn1 (num1) {
console.log("num is " + (num + num1));
console.log("我是一个嵌套函数的子函数 . ");
}
subFn1(50); // 嵌套函数的子函数的内部调用
}
fn1();
// 可以把内部函数当做外部函数的返回值 , 实现不立即执行,在任何时候调用函数内部函数都OK
// 内部函数中引用的外部函数的变量会一直存在
function fn2 () {
var num2 = 100;
function subFn2 (param) {
console.log("num2 is " + (num2 + param));
}
return subFn2; // 返回函数本身(代码块)
}
// alert(fn2()) ;
// console.log(fn2()) ;
var resultFn2 = fn2();
resultFn2(500); // 在代码某处, 想调用时在调用
// 自增操作 可以证明闭包可以让局部变量存在内存中,不被销毁
function fn3() {
var count = 0;
/*
// 第一种
function subFn3 () {
console.log("count is " + (++count));
}
return subFn3;*/
// 不用引用,返回匿名函数
return function() {
console.log("count is " + (++count));
}
}
var resultFn3 = fn3();
resultFn3();
resultFn3();
resultFn3();
console.log("***********************************************");
// 每次运行完外部函数, 都会生成一个新的内部函数
var resultFn4 = fn3(); // resultFn4 与 resultFn3是不同的引用,互不影响
resultFn4();
resultFn4();
console.log(resultFn3 === resultFn4);
// 需求 : 判断两个对象任一属性值的大小
// 创建两个字面量对象
var obj1 = {
name : "a",
age : 18
}
var obj2 = {
name : "b",
age : 15
}
// 访问对象的属性不仅有" . "语法, 还可以使用[] 来访问
// []可以用来使用为形参的属性
// 还可以用来使用有空格可属性等
console.log(obj1["name"]); // ["name"]是属性name , 如果[name]表示name是个形参
console.log(obj1.age > obj2.age); // 这只是实现了一次(完善: 封装)
// 完善 : 封装
// 比较两个对象任意属性值的大小
// 外部函数的参数要比较的属性的名字
// 用闭包实现特别的灵活
function comparePropertyFn(propertyName) {
// 返回内部函数,参数是两个要比较的对象
return function (obj1, obj2) {
// 通过属性名字获得值,用[]来用属性
var value1 = obj1[propertyName];
var value2 = obj2[propertyName];
// 判断
if(value1 > value2){
return 1;
}else if( value1 === value2){
return 0;
}else{
return -1;
}
}
}
// 获得内部比较函数
var resultCompareFn = comparePropertyFn("age");
var resultValue = resultCompareFn(obj1, obj2);
console.log(resultValue); // 1 即obj1.age > obj2.age
var resultCompareFn2 = comparePropertyFn("name");
var resultValue2 = resultCompareFn2(obj1, obj2);
console.log(resultValue2); // -1 即obj1.name < obj2.name
</script>
</head>
<body>
</body>
</html>
1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
代码一
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()());
代码二
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
};
}
};
alert(object.getNameFunc()());
JSON : JavaScript Object Notation ,是一种轻量级数据交换格式.
XML也是一种数据交换格式.但是是重量级的.但是格式清晰
JSON并不是JS独有的,大部分语言都支持JSON格式,在我们JS中, 用来和服务器端做数据格式交换的.
JSON是javascript的子集,它的结构由javascript对象和数组组成. 由这两种结构可以组合任何复杂的结构.
1.并列的数据用" , " 表示
2.映射用" : " 表示
3.并列数据的数组用" [ ] "包裹
4.并列数据的对象用" { } "包裹
1.number类型 : 和JS中的number一样
2.boolean类型 : 同JS
3.string类型 : 同JS
4.null类型 : 同JS
5.array类型 : 同JS
6.object类型 : 同JS
【序列化】
把JS对象转换成JSON格式字符串, 通过网络给其它应用程序。
JSON.stringify()方法
【反序列化】
把JSON字符串转换成JS对象.
JSON.parse()方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JSON</title>
<script type = "text/javascript">
// 创建一个自变量对象
var person = {
name : "王晓晓",
age : 27,
dog : {
dogName : "Nimo"
},
friends : [
{
friendName : "小李"
},
{
friendName : "小刘"
}
],
isMarry : false
}
// 转换成JSON格式
var jsonStr = JSON.stringify(person);
console.log(jsonStr);
// 再转回字面量对象
// 反序列化
var jsObj = JSON.parse(jsonStr);
console.log(jsObj);
</script>
</head>
<body>
</body>
</html>