【有书共读08】JS核心技术开发解密读书笔记10
JavaScript核心技术开发解密(第九、十章)读书笔记
第九章上次写笔记的童鞋写完9.1节,9.2-9.5节请参考我组Charles童鞋的博客,这里不在记录,本文主要讲解第十章ES6(上)的内容。本文关于ES6的讲解比较简单,如有兴趣还请阅读阮一峰大佬的ECMAScript
6入门。
第十章 ES6与模块化
1. 常用语法知识
let/const
在ES5中,使用var来声明一个变量。在ES6中,新的变量声明方式带来了一些不一样的特性,其中最重要的就是具备了块级作用域并且不再有变量提升(这很重要)。
下面通过一个简单的例子来说明。
// ES5 console.log(a); // undefined var a = 20; // ES6 console.log(a); // Uncaught ReferenceError: a is not defined let a = 20;
ES5存在变量提升,其实ES6也存在,但是并不会给这个变量赋值为undefined。也就是说,虽然声明提前了,但是该变量并没有任何引用,所以上例才会报ReferenceError。
由于不会默认赋值undefined,加上let/const存在自己的作用于,因此会出现一个叫作暂时性死区的现象。
因此在编写ES6代码中要注意,尽量将申明主动放置在代码的前面。
要想使用ES6,就需要全面使用let/const来替换之前非常常用的var,那么什么时候用let,什么时候用const呢?
一般来说,声明一个引用可以被改变的变量时用let,声明一个引用不能被改变的变量时用const。
例如:
let a = 20; a = 30; a = 40; console.log(a); // 40 const PI = 3.1415; const MAX_LENGTH = 100; PI = 3; // Uncaught TypeError: Assignment to constant variable
除此之外,当声明一个引用类型的数据时,也会使用const。尽管可能会改变该数据的值,但是必须保持它的引用不变。
const a = []; a.push(1); console.log(a); // [1] const b = {}; b.max = 20; b.min = 0; console.log(b); // {max: 20, min: 0}
箭头函数
与function相比,箭头函数是一个用起来更加舒服的语法。
// ES5 var fn = function (a, b) { return a + b; } // ES6 const fn = (a, b) => a + b; // ES5 var foo = function () { var a = 20; var b = 30; return a + b; } // ES6 const foo = () => { const a = 20; const b = 30; return a + b; }
需要注意,箭头函数只能替换函数表达式,即使用var/let/const声明的函数。而直接使用function声明的函数是不能使用箭头函数替换的。
箭头函数中的this,就是声明函数时所处上下文中的this,它不会被其他方式所改变。
// ES5 var name = 'Tom'; var getName = function () { console.log(this.name); } var person = { name: 'Alex', getName: getName } var other = { name: 'Joe' } getName(); // Tom,默认绑定,this指向window person.getName(); // Alex,由person调用,this指向person getName.call(other); // Joe,显示绑定,通过call使this指向other // ES6 var name = 'Tom'; var getName = () => { console.log(this.name); } var person = { name: 'Alex', getName: getName } var other = { name: 'Joe' } getName(); // Tom person.getName(); // Tom getName.call(other); // Tom
除此之外,arguments还有一个需要大家注意的地方,即在箭头函数中,没有arguments对象。
// ES5 var add = function (a, b) { console.log(arguments); return a + b; } add(1, 2); // Arguments(2) [1, 2, callee: f, Symbol(Symbol.iterator): f] // ES6 var add = (a, b) => { console.log(arguments); return a + b; } add(1, 2); // Uncaught ReferenceError: arguments is not defined
2. 模板字符串
模板字符串是为了解决传统字符串拼接不便利而出现的。
// ES5 var a = 20; var b = 30; var string = a + "+" + b + "=" + (a + b); // ES6 const a = 20; const b = 30; const string = `${a} + ${b} = ${a + b}`;
模板字符串使用反引号`将整个字符串包裹起来,变量或表达式则使用${}来包裹。
除了能够在字符串中嵌入变量,还可以用来定义多行字符串,其中所有的空格、缩进、换行都会被保留下来。
var elemString = `<div> <p>I like brother black.</p> <p>I am sorry to lose you. ${word}</p> </div>`
如果是用传统的+拼接这段字符串,则会非常麻烦(各种转义)。
${}中可以放入一个变量、表达式,甚至一个函数。
const hello = 'hello'; let message = `${hello}, world!`; const a = 20; const b = 30; let result = `the result is: ${a + b}`; let fn = () => { const result = `you are the best`; return result; } let str = `he said: ${fn()}`;
3. 解析结构(解构赋值)
解构赋值是一种从对象或者数组中取得值的一种全新的写法,只需通过一个简单的例子就能立刻明白是怎么回事(实际开发用的很多)。
// 假设存在这样一个json数据 var tom = { name: 'Tom', age: 20, gender: 1, job: 'student' } // ES5 var name = tom.name; var age = tom.age; var gender = tom.gender; var job = tom.job; // ES6 const {name, age, gender, job} = tom;
可以看到ES6解构赋值比传统赋值方便了很多,我们还可以给变量指定默认值或者重命名。
const {name = 'Jake', stature = '170'} = tom; console.log(name); // Tom,如果数据中找到name,则变量的值与数据中相等 console.log(stature); // 170,如果数据中找不到stature,则使用默认值 const {gender: t, job} = tom; console.log(gender); // Uncaught ReferenceError: gender is not defined console.log(t); // 1,重命名后gender将无法访问
我们还可以利用解构赋值获取嵌套数据中的值。
const peoples = { counts: 100, detail: { tom: { name: 'Tom', age: 20, gender: 1, job: 'student' } } } // 获取tom const {detail: {tom}} = peoples; // 获取tom的age与gender const {detail: {tom: {age, gender}}} = peoples;
此外,数组也有自己的解构赋值。当然,写法与对象的解构赋值略有不同。
const arr = [1, 2, 3]; const [a, b, c] = arr; // 等价于 const a = arr[0]; const b = arr[1]; const c = arr[2];
与对象不同的是,数组中变量和值得关系与索引是一一对应的,这是一个有序的对应关系,而对象则是根据键值对一一对应的,这是一个无序的对应关系系。因此在实践中,对象的解构赋值使用的更加频繁与便利。
4. 展开运算符
在ES6中,使用...来表示展开运算符,它可以展开数组/对象。
// 首先声明一个数组 const arr1 = [1, 2, 3]; // 其次声明另一个数组,我们希望新数组中包含数组arr1的所有元素 const arr2 = [...arr1, 4, 5, 6]; console.log(arr2); // [1, 2, 3, 4, 5, 6]
当然,展开对象也可以得到类似的结果。
const object1 = { a: 1, b: 2, c: 3 } const object2 = { ...object1, d: 4, e: 5, f: 6 } console.log(object2); {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6}
在解构赋值中,也常常使用展开运算符。
const tom = { name: 'Tom', age: 20, gender: 1, job: 'student' } const {name, ...others} = tom; console.log(others); // {age: 20, gender: 1, job: 'student'} //react中使用解构传递数据 var prop={ size: 20, src: xxx, mode: 1 }
展开运算符还可以运用在函数参数中,放置于函数参数的最后一个参数(且只能放置在最后,具体原因参考阮一峰ECMAScript6入门),表示不定参。
const add = (a, b, ...more) => { return more.reduce((m, n) => m + n) + a + n; } console.log(add(1, 23, 1, 2, 3, 4, 5)); // 39
喜欢本文的小伙伴请关注我的简书BeLLESS。最后再次感谢Charles,Cici童鞋以及牛客组织的有书共读活动,我们下期将为大家介绍剩下的关于ES6的知识,下期再见。
#读书笔记##笔记#