<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<style>
.p1 {
background-color: aqua;
}
.p2 {
background-color: blue;
}
.p3 {
background-color: brown;
}
</style>
<body>
<ul class="nav">
<li>榴莲</li>
<li>臭豆腐</li>
<li>鲱鱼罐头</li>
<li>大猪蹄子</li>
</ul>
<script>
// 闭包应用-点击li输出当前li的索引号 点击li输出当前li的索引号 点击li输出当前li的索引号
// 1. 我们可以利用动态添加属性的方式
var lis = document.querySelector('.nav').querySelectorAll('li');
lis[0].className="p1" // 修改类名,存在覆盖
lis[1].classList.add('p2') // 添加类名,不存在覆盖
for (var i = 0; i < lis.length; i++) { // 这是一个同步任务会立马执行
lis[i].index = i; //重点核心重点核心,先给每个li一个可以表示索引的属性
// 给每个li绑定事件
lis[i].onclick = function() { // 这是一个异步任务
// console.log(i);
console.log(this.index);
}
}
// 经典面试题
// 2. 利用闭包的方式得到当前小li 的索引号
for (var i = 0; i < lis.length; i++) {
// 利用for循环创建了4个立即执行函数
// 立即执行函数也称为小闭包因为立即执行函数里面的任何一个函数都可以使用它的i这变量
(function(i) {
// console.log(i);
lis[i].onclick = function() {
console.log(i);
this.classList.add('p3')
// 因为这里面有个异步任务,
// 所以立即函数创建之后不会立即销毁而是等待着异步任务调用后再进行销毁
// 所以这种方法容易造成内存泄
}
})(i);
// ()()立即执行函数
// (function(){})()
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<ul class="nav">
<li>榴莲</li>
<li>臭豆腐</li>
<li>鲱鱼罐头</li>
<li>大猪蹄子</li>
</ul>
<script>
// 闭包应用-3秒钟之后,打印所有li元素的内容
var lis = document.querySelector('.nav').querySelectorAll('li');
for (var i = 0; i < lis.length; i++) { //同步任务
(function (i) {
setTimeout(function () { // 定时器也是一个异步任务
console.log(lis[i].innerHTML);
}, 3000)
})(i);
}
// js执行机制同步完了在去执行执行队列里面的异步任务
// for(var i=0;i<数组名.length;i++){
// setTimeout(function(){
// console.log(数组名[i].innerHTML) //会报错,拿不到i
// },毫秒数)
// }
//
//
</script>
</body>
</html>
异步任务拿取不到同步任务使用的变量或者索引时,经常使用1:在一循环开始时就对每个对象就是每个元素标签设置能够表示索引的属性,(就是直接在for里面紧跟着 lis[i].index = i; )
2:利用立即执行函数, (function(i){}) (i)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<!-- // 闭包(closure闭包其实是一个闭包函数)指有权访问另一个函数作用域中变量的函数。
// 简单理解就是,一个作用域可以访问到另外一个函数内部的局部变量 -->
<!-- 闭包(closure)指有权访问另一个函数作用域中变量的函数。 ,就是我们可以做默认的初始值,并且可以返回给全局使用
// 一个作用域可以访问另外一个函数的局部变量
// 闭包的主要作用: 延伸了变量的作用范围 -->
<body>
<script>
// 闭包应用-计算打车价格
// 打车起步价13(3公里内), 之后每多一公里增加 5块钱. 用户输入公里数就可以计算打车价格
// 如果有拥堵情况,总价格多收取10块钱拥堵费
// function fn() {};
// fn();
var car = (function() {
var start = 13; // 起步价 局部变量
var total = 0; // 总价 局部变量
return {
// 正常的总价
price: function(n) {
if (n <= 3) {
console.log(start) // 这里访问了闭包函数,所以当n<=3时,它的初始值是13
total = start;
} else {
total = start + (n - 3) * 5
}
return total;
},
// 拥堵之后的费用
yd: function(flag) { // true 就是满足拥堵的时候
return flag ? total + 10 : total;
}
}
})();
console.log(car) // Object {price: ƒ, yd: ƒ}
console.log(car.price(5)); // 23 //传参后之前存储的数值就被传入后算出的数值给改变了,
console.log(car.yd(true)); // 33
console.log(car.price(1)); // 13
console.log(car.yd(false)); // 13
</script>
</body>
</html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <script> // 用一个变量名接收的是一个返回函数,那么使用变量f()就是调用了这个函数 等价于 对象.函数名()() // 思考题 1: var name = "The Window"; var object = { name: "My Object", getNameFunc: function() { return function() { return this.name; }; } }; console.log(object.getNameFunc()()) // The Window var f = object.getNameFunc(); // 类似于 var f = function() { return this.name; } // 普通函数的作用域指向全局 f(); // function(){this}() 这个this执行的windows,但是它的使用必须需要一个()包裹起来 var f1 = function(){ return console.log(this) } f1() //这里打印出来的this指向window // 思考题 2: var name = "The Window"; var object = { name: "My Object", getNameFunc: function() { var that = this; return function() { return that.name+this.name; }; } }; console.log(object.getNameFunc()()) //My ObjectThe Window var name = "The Window"; var object = { name: "My Object", getNameFunc: function() { // var that = this; return function() { return this.name; }; } }; console.log(object.getNameFunc()()) // The Window </script> </body> </html>
<body>
<script>
// 利用递归函数求1~n的阶乘 1 * 2 * 3 * 4 * ..n
function fn(n) {
if (n == 1) {
return 1;
}
return n * fn(n - 1);
}
console.log(fn(3));// 6
console.log(fn(4)); // 24
// 详细思路 假如用户输入的是3
//return 3 * fn(2)
//return 3 * (2 * fn(1))
//return 3 * (2 * 1)
//return 3 * (2)
//return 6
</script>
</body>