时间:2022-09-10 09:20:37 | 栏目:JavaScript代码 | 点击:次
JavaScript 的创造者 Netscape 公司,决定将 JavaScript 提交给标准化组织 ECMA,希望这种语言能够成为国际标准,但是JavaScript本身也已经被 Netscape 公司注册为商标,后面的标准都由ECMA制定,取名ECMAScript。
那么ES6这个版本引入的新内容较多,通常指JavaScript语言的下一个版本。
ES6 新增了let
命令,用来声明变量。它的用法类似于var
,但是所声明的变量,只在let
命令所在的代码块内有效。
var和let定义变量区别:
<script> //var的作用域是函数级的(函数内部定义变量只能函数里面使用) // function showName() // { // var myName = "张学友"; // alert(myName + "欢迎您!"); //此处的myName为"张学友" // } // showName(); // alert(myName + "欢迎您!"); //此处会报错,myName只能在showName函数中使用 //var的作用域是函数级的(在代码块中定义的变量可以在代码块之外使用) // if(1==1) // { // var myName = "张学友"; // } // alert(myName + "欢迎您!"); //此处可以运行 //let的作用域是代码块级别的 // if(1==1) // { // let myName = "张学友"; // } // alert(myName + "欢迎您!"); //此处会报错 //let不存在变量提升 // console.log(a); //报错 // let a = "apple"; // console.log(b); //undefined // var b = "banana"; </script>
var和let在循环计数时候的区别:
<script> // for(var i = 1;i <= 10;i++) // { // // // } // alert(i); //此处会打印11,i在循环体内和循环体外都可以使用 //此时计数器的变量泄露成了全局变量 // for(let i = 1;i <= 10;i++) // { // // // } // alert(i); //此处会报错,i只在循环体内有效,在循环体外无效 // 输出十个11 // i是全局的,定时器代码在循环之后发生,所以打印十个11 // for (var i = 1; i <= 10; i++) { // setTimeout(function(){ // console.log(i); // }) // } //输出1 2 3 4 5 6 7 8 9 10 for (let j = 1; j <= 10; j++) { setTimeout(function(){ console.log(j); }) } </script>
循环绑定网页元素事件中var和let的区别:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>循环绑定按钮事件</title> </head> <body> <h2>点击三个按钮分别弹出1,2,3</h2> <input type="button" class="myButton" value="第一个按钮" /> <input type="button" class="myButton" value="第二个按钮"/> <input type="button" class="myButton" value="第三个按钮"/> </body> </html> <script> //在此案例中i是全局的,点击按钮发生在循环之后,所以打印结果全部为4 // var list = document.getElementsByClassName("myButton"); // for(var i = 0;i < list.length;i++) // { // list[i].onclick = function(){ // alert(i+1); // } // } //上述代码不能打印1,2,3,而是打印4,需要采取JS闭包来解决此问题; //闭包就是能够读取其他函数内部变量的函数 // var list = document.getElementsByClassName("myButton"); // for(var i = 0;i < list.length;i++) // { // list[i].onclick = (function(num) // { // return function(){ // alert(num); // } // })(i+1); // } //如果使用ES6中let关键字则不存在上面演示的问题 var list = document.getElementsByClassName("myButton"); for(let i = 0;i < list.length;i++) { list[i].onclick = function(){ alert(i+1); } } </script>
const
声明一个只读的常量。一旦声明,常量的值就不能改变。
<script> // const PI = 3.14; // PI = 3.15; //此处会报错,const声明的变量不能改变其值 //const一旦声明变量,就必须立即初始化,不能留到以后赋值。 //const PI; //报错 //const实际上保证的,并不是变量的值不得改动, //而是变量指向的那个内存地址所保存的数据不得改动。 const arr = []; arr.push('jack'); //可以执行 arr.push("rose"); //可执行 console.log(arr[0]); console.log(arr[1]); </script>
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值
// let a = 1; // let b = 2; // let c = 3; //上述代码可以如下编写(从数组中提取值,按照对应位置,对变量赋值) // let[a,b,c]=[1,2,3];
数组解构赋值案例:
//let [a, [[b], c]] = [1, [[2], 3]]; //a=1,b=2,c=3 //let [ , , c] = ["jack", "rose", "mike"]; //c=mike //let [x, , y] = [1, 2, 3]; //x=1,y=3 //let [head, ...tail] = [1, 2, 3, 4]; //head=1,tail=[2,3,4] //let [x, y, ...z] = ['a']; //x=a,y=undefined,z=[]
解构不成功,变量的值就等于undefined:
//let [foo] = []; //解构不成功,foo=undefined //let [bar, foo] = [1]; //bar=1,foo解构不成功foo=undefined
不完全解构:
左边的模式只能匹配右边的一部分,也可以解构成功:
let [x, y] = [1, 2, 3]; //x=1,y=2
字符串解构(将字符串当成一个数组):
let [a, b, c, d, e] = 'hello'; console.log(a); console.log(b); console.log(c); console.log(d); console.log(e);
默认值:
解构赋值允许指定默认值
//let [foo = true] = []; //foo=true; //let [x, y = 'b'] = ['a']; // x='a', y='b' //let [x, y = 'b'] = ['a', undefined]; // x='a', y='b' //let [x = 1] = [null]; //x=null(只有当一个数组等于undefined,默认值才会生效)
默认值可以引用解构赋值的其他变量,但该变量必须已经声明
//let [x = 1, y = x] = []; // x=1; y=1 //let [x = 1, y = x] = [2]; // x=2; y=2 //let [x = 1, y = x] = [1, 2]; // x=1; y=2 //let [x = y, y = 1] = []; // ReferenceError: y is not defined
解构不仅可以用于数组,还可以用于对象。
let { foo, bar } = { foo: 'aaa', bar: 'bbb' }; //foo='aaa', bar='bbb'
以上代码看上去和数组解构赋值没有多大区别,但是:
(1) 数组解构中数组的元素是按次序排列的,变量的取值由它的位置决定;
(2) 对象解构中对象的属性没有次序,变量必须与属性同名,才能取到正确的值 ;
如下:
let { bar, foo } = { foo: 'aaa', bar: 'bbb' }; //foo="aaa" bar= "bbb" let { baz } = { foo: 'aaa', bar: 'bbb' }; //baz = undefined,解构失败,值为undefined
对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量:
// 例一 let { log, sin, cos } = Math; //将Math对象的对数、正弦、余弦三个方法,赋值到对应的变量上 // 例二 const { log } = console; //将console.log赋值到log变量,简化代码 log('hello') // hello
如果变量名与属性名不一致,必须写成下面这样:
let { foo: baz } = { foo: 'aaa', bar: 'bbb' }; //baz = "aaa" let obj = { first: 'hello', last: 'world' }; let { first: f, last: l } = obj; //f = 'hello' l = 'world'
这实际上说明,对象的解构赋值是下面形式的简写
let { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb' };
真正被赋值的是后者,而不是前者:
let { foo: baz } = { foo: 'aaa', bar: 'bbb' }; //baz = "aaa" foo = error: foo is not defined
与数组一样,解构也可以用于嵌套结构的对象 :
let obj = { p: [ 'Hello', { y: 'World' } ] }; let { p: [x, { y }] } = obj; x // "Hello" y // "World"
注意,这时p
是模式,不是变量,因此不会被赋值。如果p
也要作为变量赋值,可以写成下面这样。
let obj = { p: [ 'Hello', { y: 'World' } ] }; let { p, p: [x, { y }] } = obj; x // "Hello" y // "World" p // ["Hello", {y: "World"}]
默认值:
let {x = 3} = {}; x // 3 let {x, y = 5} = {x: 1}; x // 1 y // 5 let {x: y = 3} = {}; y // 3 let {x: y = 3} = {x: 5}; y // 5 let { message: msg = 'Something went wrong' } = {}; msg // "Something went wrong"
默认值生效的条件是,对象的属性值严格等于undefined
var {x = 3} = {x: undefined}; x // 3 var {x = 3} = {x: null}; x // null
注意点:
如果要将一个已经声明的变量用于解构赋值,必须非常小心
// 错误的写法 let x; {x} = {x: 1};
上面代码的写法会报错,因为 JavaScript 引擎会将{x}
理解成一个代码块, 只有不将大括号写在行首,才能解决
这个问题。
// 正确的写法 let x; ({x} = {x: 1});
由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。
let arr = [1, 2, 3]; let {0 : first, [arr.length - 1] : last} = arr; //利用数组下标解构赋值 first // 1 last // 3