拓展:块级作用域var、let、const的使用
let/var
事实上var的设计可以看成JavaScript语言设计上的错误. 但是这种错误多半不能修复和移除, 以为需要向后兼容.
- 大概十年前, Brendan Eich就决定修复这个问题, 于是他添加了一个新的关键字: let.
- 我们可以将let看成更完美的var
块级作用域
- JS中使用var来声明一个变量时, 变量的作用域主要是和函数的定义有关.
- 针对于其他块定义来说是没有作用域的,比如if/for等,这在我们开发中往往会引起一些问题。
块级作用域
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<button>按钮5</button>
<script>
// ES5中的var是没有块级作用域的(if/for)
// ES6中的let是由块级作用的(if/for)
// ES5之前因为if和for都没有块级作用域的概念, 所以在很多时候, 我们都必须借助于function的作用域来解决应用外面变量的问题.
// ES6中,加入了let, let它是有if和for的块级作用域.
// 1.变量作用域: 变量在什么范围内是可用.
// {
// var name = 'why';
// console.log(name);
// }
// console.log(name);
// 2.没有块级作用域引起的问题: if的块级
// var func;
// if (true) {
// var name = 'why';
// func = function () {
// console.log(name);
// }
// // func()
// }
// name = 'kobe'
// func()
// // console.log(name);
var name = 'why'
function abc(bbb) { // bbb = 'why'
console.log(bbb);
}
abc(name)
name = 'kobe'
// 3.没有块级作用域引起的问题: for的块级
// 为什么闭包可以解决问题: 函数是一个作用域.
// var btns = document.getElementsByTagName('button');
// for (var i=0; i<btns.length; i++) {
// (function (num) { // 0
// btns[i].addEventListener('click', function () {
// console.log('第' + num + '个按钮被点击');
// })
// })(i)
// }
const btns = document.getElementsByTagName('button')
for (let i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击');
})
}
// ES5
// var i = 5
// {
// btns[i].addEventListener('click', function () {
// console.log('第' + i + '个按钮被点击');
// })
// }
//
// {
// btns[i].addEventListener('click', function () {
// console.log('第' + i + '个按钮被点击');
// })
// }
//
//
// {
// btns[i].addEventListener('click', function () {
// console.log('第' + i + '个按钮被点击');
// })
// }
//
//
// {
// btns[i].addEventListener('click', function () {
// console.log('第' + i + '个按钮被点击');
// })
// }
//
// {
// btns[i].addEventListener('click', function () {
// console.log('第' + i + '个按钮被点击');
// })
// }
//
// // ES6
// { i = 0
// btns[i].addEventListener('click', function () {
// console.log('第' + i + '个按钮被点击');
// })
// }
//
// { i = 1
// btns[i].addEventListener('click', function () {
// console.log('第' + i + '个按钮被点击');
// })
// }
// { i = 2
// btns[i].addEventListener('click', function () {
// console.log('第' + i + '个按钮被点击');
// })
// }
// { i = 3
// btns[i].addEventListener('click', function () {
// console.log('第' + i + '个按钮被点击');
// })
// }
// { i = 4
// btns[i].addEventListener('click', function () {
// console.log('第' + i + '个按钮被点击');
// })
// }
</script>
</body>
</html>
块级作用域(es5没闭包-有闭包-let对比)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<script>
// 1.没有块级作用域引起的问题: for的块级
// 为什么闭包可以解决问题: 函数是一个作用域.
var btns = document.getElementsByTagName('button');
for (var i=0; i<btns.length; i++) {
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击');
})
}
// 1.情况一: ES5中没有使用闭包(错误的方式)
i = 2
{
// i = 0
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击');
})
}
{
i = 1
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击');
})
}
{
// i = 2
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击');
})
}
// 2.情况二: ES5中使用闭包
var btns = document.getElementsByTagName('button');
for (var i=0; i<btns.length; i++) {
(function (i) { // 0
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击');
})
}) (i)
}
i = 100000000
function (i) { // i = 0
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击');
})
}(0)
function (i) { // i = 1
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击');
})
}(1)
function (i) { // i = 2
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击');
})
}(2)
// ES6中的let
const btns = document.getElementsByTagName('button')
for (let i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击');
})
}
i = 10000000
{ i = 0
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击');
})
}
{ i = 1
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击');
})
}
{ i = 2
btns[i].addEventListener('click', function () {
console.log('第' + i + '个按钮被点击');
})
}
</script>
</body>
</html>
const的使用
const关键字
- 在很多语言中已经存在, 比如C/C++中, 主要的作用是将某个变量修饰为常量.
- 在JavaScript中也是如此, 使用const修饰的标识符为常量, 不可以再次赋值.
什么时候使用const呢?
- 当我们修饰的标识符不会被再次赋值时, 就可以使用const来保证数据的安全性.
**建议: 在ES6开发中,优先使用const, 只有需要改变某一个标识符的时候才使用let. **
const的注意
-
const注意一:
-
const注意二:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
// 1.注意一: 一旦给const修饰的标识符被赋值之后, 不能修改
// const name = 'why';
// name = 'abc';
// 2.注意二: 在使用const定义标识符,必须进行赋值
// const name;
// 3.注意三: 常量的含义是指向的对象不能修改, 但是可以改变对象内部的属性.
const obj = {
name: 'why',
age: 18,
height: 1.88
}
// obj = {}
console.log(obj);
obj.name = 'kobe';
obj.age = 40;
obj.height = 1.87;
console.log(obj);
</script>
</body>
</html>
对象增强写法
- ES6中,对对象字面量进行了很多增强。
- 属性初始化简写和方法的简写:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
// const obj = new Object()
// const obj = {
// name: 'why',
// age: 18,
// run: function () {
// console.log('在奔跑');
// },
// eat: function () {
// console.log('在次东西');
// }
// }
// 1.属性的增强写法
const name = 'why';
const age = 18;
const height = 1.88
// ES5的写法
// const obj = {
// name: name,
// age: age,
// height: height
// }
// const obj = {
// name,
// age,
// height,
// }
//
// console.log(obj);
// 2.函数的增强写法
// ES5的写法
// const obj = {
// run: function () {
//
// },
// eat: function () {
//
// }
// }
const obj = {
run() {
},
eat() {
}
}
</script>
</body>
</html>