return的运用1:返回 参数传入的对象
function setObjProper(obj) {
obj = obj || {}; //如果obj不存在就给他一个新对象————宽模式。
obj.n = 3;
return obj;
}
var obj = setObjProper({});
var obj1 = setObjProper();
console.log(obj, obj1);
return的运用2:函数的参数是函数,返回回调函数的结果
function fn2(fn) {
var obj = {};
return fn(obj);
}
function fn3(obj) {
obj.a = 10;
return obj;
}
function fn4(obj) {
obj.b = 10;
return obj;
}
var obj = fn2(fn3);
console.log(obj);
return的运用3: 函数中返回一个函数体叫做闭包。
举一个简单的例子:
function fn5() {
return function() {
console.log("aaa");
}
}
fn5()();
那么什么是闭包呢?
闭包(closure)是计算机编程领域的专业名词,指可以包含自由(未绑定到特定对象)变量的代码块,子函数可以使用父函数中的局部变量。闭包源于要执行的代码块和为自由变量提供绑定的计算环境(作用域)两者的结合,Scala、Scheme、Common Lisp、Smalltalk、Groovy、JavaScript、Ruby、 Python、Lua、objective c 以及Java(Java8及以上)等语言中都能找到对闭包不同程度的支持。
简单来说,闭包指有权访问另一个函数作用域中的变量的函数。即 一个作用域可以访问另一个函数的局部变量。闭包的主要作用就是延伸了变量的作用范围。
比如以下代码:
function fn() {
var num = 10;
function fun() {
console.log(num);
}
// fun();
return fun; //return一个函数
}
// fn();
var f = fn();
f();
// 类似于:
// var f = function fun() {
// console.log(num);
// }
举三个闭包的小案例
<ul class="nav">
<li>榴莲</li>
<li>臭豆腐</li>
<li>鲱鱼罐头</li>
<li>大猪蹄子</li>
</ul>
闭包应用1:点击li输出当前li的索引号
// 1.我们可以用动态添加属性的方式
var lis = document.querySelector('.nav').querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {
lis[i].index = i;
lis[i].onclick = function() {
console.log(this.index);
}
}
// 2.利用闭包的方式得到当前小li的索引号
for (var i = 0; i < lis.length; i++) {
// 利用for循环创建了4个立即执行函数
(function(i) {
lis[i].onclick = function() {
console.log(i);
}
})(i);
}
通过对比上面两种方法,可以发现虽然闭包有好处,但是不是所有的闭包都更方便,因为循环一次就会创建一次立即执行函数。所以在开发中要考虑选择。
闭包运用2:3秒钟之后打印li元素中的所有内容
var lis = document.querySelector('.nav').querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {
(function(i) {
setInterval(function() {
console.log(lis[i].innerHTML);
}, 3000)
})(i);
}
闭包运用3:计算打车价格
打车起步价13(3公里内),之后每多一公里增加5块钱.用户输入公里数就可以计算打车价格;如果有拥堵情况,总价格多收取10块钱拥堵费。
var car = (function() {
var start = 13;
var total = 0;
return {
price: function(n) { //正常的总价
if (n <= 3) {
total = start;
} else {
total = start + (n - 3) * 5;
}
return total;
},
yongdu: function(flag) { //拥堵的费用
return flag ? total + 10 : total;
}
}
})();
console.log(car.price(5));
console.log(car.yongdu(true));
console.log(car.price(3));
console.log(car.yongdu(false));
两个闭包的思考题
// 闭包思考题1
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function() {
return function() {
return this.name; //this指的就是window
};
}
};
console.log(object.getNameFunc()()); //The Window
分析一下代码的最后一句:
// object.getNameFunc()()类似于:
var f = object.getNameFunc();
f();
//object.getNameFunc() 类似于:
var f = function() {
return this.name;
}
console.log(f());
此段代码没有闭包的产生,因为没有局部变量的产生。
// 闭包思考题2
var name = "The Window";
var object = {
name: "My Object",
getNameFunc: function() {
var that = this; //这里的this指的是object
return function() {
return that.name; //this指的就是window
};
}
};
console.log(object.getNameFunc()()); //My Object
分析一下最后一句:
// object.getNameFunc()()类似于:
var f = object.getNameFunc();
// object.getNameFunc()类似于:
var f = function() {
return that.name;
};
console.log(f());
object调用了getNameFunc()这个函数,那么这个函数就会去执行。由于这时是object调用的函数,所以 var that = this 中的this指的是object。
此段代码产生了闭包吗?
查看是否有闭包的方法:打开浏览器控制台-sources-return that.name这一句上加断点-刷新页面-Scope-Closure(getNameFunc)
总结:
- 闭包是一个函数(一个作用域可以访问另外一个函数的局部变量)
- 闭包的作用是延伸了变量的作用范围。