一直没有系统地学习JS。这次谷歌刚好找到了一本还不错的书,学习ES6语法,顺带提升一下JS的基础知识。
let 和 const 命令
Let 命令:
不存在变量提升:
let
定义后才能使用,如果在之前有引用,会报错。var
则不会报错,只会提示:undefined
。
暂时性死区:
这个和上面的一样,在声明前如果引用,会报错。
不能重复声明:
在同一作用域内只能声明一次。
块级作用域:
这里对作用域有了新的认识:
比如上面的for循环,每循环一次,就是一个独立的作用域。还包括IF语句,也是一个独立的作用域。
let
的作用域:var
为全局作用域,如果在块级作用域里var
定义,会泄露到全局作用域。let
只在作用域内有效。不会泄露。
什么是立即执行函数表达式(IIFE)?
通常想要定义好的函数表达式马上执行,需要在声明后调用,;如果想立即执行:
123 > (function(){/* code */}());> (function(){/* code */})();>
>
可以像这样用括号从最外面包起来。函数这会立即执行。
关于Javascript的函数声明和函数表达式:
块级作用域与函数声明
如果在作用哉里声明,会被提升到作用哉前面,并被当全局函数。
所以:尽量减少在块级作用域里写函数声明。要也是尽量写成函数表达式。
在ES5时代,如果拥有块级变量呢?
可以参考这篇博客:JavaScript的作用域和块级作用域概念理解
原理:
- 在一个函数中定义的变量,当这个函数调用完后,变量会被销毁
所以:
123(function (){//内容})();这里面运行的东西和声明的变量就属于块级的了!
Const
const
声明一个只读的常量。一旦声明,常量的值就不能改变。const
命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。const
的作用域与let
命令相同:只在声明所在的块级作用域内有效。const
声明的常量,也与let
一样不可重复声明。
变量的解构赋值
数组的解构赋值
和ruby和赋值模式差不多,但这里只是以数组的形式出现在赋值的时候:
1234let [a, b, c] = [1, 2, 3];let [head, ...tail] = [1, 2, 3, 4];head // 1tail // [2, 3, 4]默认值:
123let [x = 1] = [undefined];x // 1let [x = 1, y = x] = [2]; // x=2; y=2这里意思是先对比变量和最右边的数是否
====
严格相等,如果不是就执行左边的赋值。对象ObJ也可以被用来这样赋值。(其中有一些)
字符串也可以这样:
123456const [a, b, c, d, e] = 'hello';a // "h"b // "e"c // "l"d // "l"e // "o"作用:
交换变量的值
1234let x = 1;let y = 2;[x, y] = [y, x];从函数返回多个值
12345678910111213141516// 返回一个数组function example() {return [1, 2, 3];}let [a, b, c] = example();// 返回一个对象function example() {return {foo: 1,bar: 2};}let { foo, bar } = example();函数参数的定义
&&函数参数默认值
1234567891011jQuery.ajax = function (url, {async = true,beforeSend = function () {},cache = true,complete = function () {},crossDomain = false,global = true,// ... more config} = {}) {// ... do stuff};提取 JSON 数据
12345678910let jsonData = {id: 42,status: "OK",data: [867, 5309]};let { id, status, data: number } = jsonData;console.log(id, status, number);// 42, "OK", [867, 5309]
字符串
字符串模板:
1`my name is ${name}.` #类似ruby的模板。
函数定义
默认值惰性传值:
123456789let x = 99;function foo(p = x + 1) {console.log(p);}foo() // 100x = 100;foo() // 101上面代码中,参数
p
的默认值是x + 1
。这时,每次调用函数foo
,都会重新计算x + 1
,而不是默认p
等于 100。name 属性
函数的
name
属性,返回该函数的函数名。箭头函数
1234567// 正常函数写法[1,2,3].map(function (x) {return x * x;});// 箭头函数写法[1,2,3].map(x => x * x);this
的作用域:1234567891011121314151617function Timer() {this.s1 = 0;this.s2 = 0;// 箭头函数setInterval(() => this.s1++, 1000);// 普通函数setInterval(function () {this.s2++;}, 1000);}var timer = new Timer();setTimeout(() => console.log('s1: ', timer.s1), 3100);setTimeout(() => console.log('s2: ', timer.s2), 3100);// s1: 3// s2: 0上面代码中,
Timer
函数内部设置了两个定时器,分别使用了箭头函数和普通函数。前者的this
绑定定义时所在的作用域(即Timer
函数),后者的this
指向运行时所在的作用域(即全局对象)。所以,3100 毫秒之后,timer.s1
被更新了 3 次,而timer.s2
一次都没更新。