问题一
1. 难度系数: ★★★
2. 技术点:
1). 变量提升
2). 函数提升
3). 预处理
预热一
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>04_阿里1</title>
</head>
<body>
<script type="text/javascript">
// 预热一
var a = 2
function fn() { // 预计处理:
/*
var a;
console.log(a)
a = 3
*/
console.log(a)
var a = 3
}
fn() // ?
function fn2() { // 预计处理:
console.log(a)
a = 3 // a是全局变量
}
fn2() // ?
</script>
</body>
</html>
1.
var a = 2
function fn() { // 预计处理:
console.log(a)
var a = 3
}
fn() // ?
输出:fn() --undefined
按正常的原型链来分析可知结果应为 2;但结果为undefined ;因为在执行函数 fn 之前有预处理 ,执行预处理的代码为
var a = 2
function fn() { // 预计处理:
var a;
console.log(a)
var a = 3
}
fn() // ?
故知输出为 undefined
将 var a = 3 改为 a=3,则输出为 2
var a = 2
function fn() { // 预计处理:
console.log(a)
a = 3
}
fn() // ?
这时 a 是全局变量,按正常的原型链来分析可知结果应为 2
预热二
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>04_阿里1</title>
</head>
<body>
<script type="text/javascript">
// 预热二 预计处理是变量先还是函数先? 变量--->函数
function b() {
}
var b
console.log(typeof b) // ? function
</script>
</body>
</html>
function b() 和 var b 都有预处理,但 先预处理变量还是预处理函数? ---变量先预处理,再预处理函数,故输出类型为 function
正式题目
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>04_阿里1</title>
</head>
<body>
<script type="text/javascript">
var c = 1
function c(c) { //申明形参 c
console.log(c)
var c = 3
}
console.log(c) // ? 1
c(2) // ?
</script>
</body>
</html>
输出:把 1 当做函数来调用 导致报错
预处理:在代码执行之前完成的任务 1. 收集用var声明变量 2. 收集用function声明函数
函数与变量区别: 函数名=函数 变量名=非函数
问题二
1. 难度系数: ★★★
2. 技术点:
1). 变量提升
2). IIFE
3). 作用域与作用域链
4). 变量查找
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>05_腾讯2</title>
</head>
<body>
<script type="text/javascript">
var name = 'World!';
(function () {
/*
var name //变量提升(执行if前执行,故=undefined)
.....
*/
if (typeof name === 'undefined') {
var name = 'Jack'
console.log(name) //输出 Jack
} else {
console.log(name) //输出 World
}
})()
</script>
</body>
</html>
输出:Jack
问题三
1. 难度系数: ★★★
2. 技术点
1). 定时器
2). 意外全局变量
3). 作用域与作用域链
4). 变量查找
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>06_阿里2</title>
</head>
<body>
<script type="text/javascript">
var a = 6
setTimeout(function () {
console.log(0)
alert(a)
a = 666
}, 0) //0 毫秒之后执行
console.log(1)
a = 66
/*
1 , 0 谁先输出? 1先执行
*/
</script>
</body>
</html>
输出:
虽然定时器的时间设为了 0,但它是异步的,必须先将外部同步的代码执行完了之后才能执行异步的回调函数;即先执行a=66,故alert的值为66,然后将666赋值给 a,即a的值由6变为666
问题四
1. 难度系数: ★★★
2. 技术点:
1). DOM事件处理
2). 闭包
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>07_腾讯3</title>
</head>
<body>
<button>测试1</button>
<button>测试2</button>
<button>测试3</button>
<script type="text/javascript">
/*
需求: 点击某个按钮, 提示"第n个"
问题: 下面的实现代码是否正确, 如果不正确, 请正确实现
*/
var btns = document.getElementsByTagName('button') //得到所有按钮
for(var i=0,length=btns.length;i<length;i++) { // i是一个全局变量, 遍历后是3
var btn = btns[i] //得到某个按钮
btn.onclick = function () { //绑定点击监听
alert('第'+(i+1)+'个')
}
}
</script>
</body>
</html>
输出:无论点击那个均输出第4个,故代码存在问题
问题在于函数在 for 循环执行之后才执行,for 循环执行之后 i 的值是全局变量,故输出4
修改代码
1.ES6语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>07_腾讯3</title>
</head>
<body>
<button>测试1</button>
<button>测试2</button>
<button>测试3</button>
<script type="text/javascript">
/*
需求: 点击某个按钮, 提示"第n个"
问题: 下面的实现代码是否正确, 如果不正确, 请正确实现
*/
var btns = document.getElementsByTagName('button') //得到所有按钮
for(let i=0,length=btns.length;i<length;i++) { // i是一个全局变量, 遍历后是3
var btn = btns[i] //得到某个按钮
btn.onclick = function () { //绑定点击监听
alert('第'+(i+1)+'个')
}
}
</script>
</body>
</html>
输出:将 var 改为 let (ES6语法)
2.闭包
产生闭包条件:1.有函数嵌套 2.内部函数引用了外部函数的局部变量
闭包示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>07_腾讯3</title>
</head>
<body>
<script type="text/javascript">
function fn1() {
var a = 2
function fn2 () { //闭包由嵌套的内部函数产生,(a=2)存在于当前内部函数fn2的内部
a++
console.log(a)
}
return fn2
}
var f = fn1()
f() //输出3 (2+1=3)
f() //输出4
</script>
</body>
</html>
输出:
用闭包的方法改写上述代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>07_腾讯3</title>
</head>
<body>
<button>测试1</button>
<button>测试2</button>
<button>测试3</button>
<script type="text/javascript">
/*
需求: 点击某个按钮, 提示"第n个"
问题: 下面的实现代码是否正确, 如果不正确, 请正确实现
*/
/* var btns = document.getElementsByTagName('button') //得到所有按钮
for(let i=0,length=btns.length;i<length;i++) { // i是一个全局变量, 遍历后是3
var btn = btns[i] //得到某个按钮
btn.onclick = function () { //绑定点击监听
alert('第'+(i+1)+'个')
}
}*/
var btns = document.getElementsByTagName('button') //得到所有按钮
for(var i=0,length=btns.length;i<length;i++) { // i是一个全局变量, 遍历后是3
(function (i) {
var btn = btns[i] //得到某个按钮
btn.onclick = function () { //绑定点击监听
alert('第'+(i+1)+'个')
}
})(i) // 使用了闭包--->内存中产生了1+3个i
}
</script>
</body>
</html>
输出: