1. 通过let const可以提高性能
- ES6增加这两个关键字不仅有助于改善代码风格,而且同样有助于改进垃圾回收的过程。因为const和let都以块(而非函数)为作用域,所以相比于使用var,使用这两个新关键字可能会更早地让垃圾回收程序介入,尽早回收应该回收的内存。在块作用域比函数作用域更早终止的情况下,这就有可能发生。
2. 隐藏类
- V8在运行期间会把创建的对象与隐藏类关联起来,用来跟踪他们的属性特征。
上面代码两个实例共享相同的隐藏类,因为两个实例共享同一个构造函数和原型,但是如果执行了如下代码function Article(){ this.text = "这是一个构造器" } let a1 = new Article() let a2 = new Article()
这个时候出现的Article实例就对应两个不同的隐藏类,会开辟新内存,所以需要做到“先创建再补充”,在构造器内部一次性声明所有的属性a2.author = "Jake"
同样的,动态删除属性也会创建新的隐藏类,最佳的实践方法就是把不想要的属性设置为null,可以保持隐藏类不变。function Article(author) { this.title = '这是一个构造器'; this.author = author; } let a1 = new Article(); let a2 = new Article('Jake');
3.原始值包装类型
-
为了方便操作原始值,JS提供了三种特殊的引用类型:Boolean,Number和String。和引用类型具有一样的特点,但是也具有与各自原始类型对象的特殊行为。每当用到某个原始值的方法或属性时,后台都会创建一个相应原始包装类型的对象
let s1 = "这是一个字符串"; let s2 = s1.substring(2);
上面s1创建了一个原始值,第二行却又使用原始值调用substring()方法。
一般原始值本身并不是对象,逻辑上讲应该是没有方法的,但是却可以调用方法,本质其实是后台做了很多的处理。第二步访问s1时,是以读模式访问,也就是要从内存中读取变量保存的值。在以读模式访问字符串值的时候,后台都会执行:
- 创建一个String实例
- 调用实例上特定的方法
- 销毁实例
//上面两行代码的拆解 let s1 = new String("这是一个字符串") let s2 = s1.substring(2) let s1 = null
这中行为让原始值具有了对象的行为。布尔值和Number也是会发生上面的步骤的,只不过使用的是别的包装类型
注意:引用类型和原始值的包装类型区别主要在于其生命周期。在通过new实例化引用类型后,得到的实例会在离开作用域的时候被销毁,而创建的包装类型只存在于访问它的那段代码执行期间,所以我们在使用的时候是不可以给原始值添加属性和方法的。
-
如果给Object传字符串,则会创建一个String实例,如果是数值,则会创建Number实例,Boolean同理
let obj = new Object("字符串") console.log(obj instanceof String); //true
使用new调用原始值包装类型的构造函数,与调用同名的转型函数不一样
let value = "25"; let number = Number(value); // 转型函数 console.log(typeof number); // "number" let obj = new Number(value); // 构造函数 console.log(typeof obj); // "object"
变量number保存的是一个值25的原始数值,而变量obj保存的是一个Number的实例。
4. 集合引用类型
- Array构造函数有两个Es6新增用于创建数组的静态方法:from()和of(),from用于将数组结构转化成数组实例,of将参数转换成数组实例
-
Array.from()
Array.from("Array") //[ 'A', 'r', 'r', 'a', 'y' ] Array.from("我操,说藏话了")//['我', '操',',', '说','藏', '话','了']
form()还有第二个参数,可以增强新数组的值
const a1 = [1, 2, 3, 4, 5]; const a2 = Array.from(a1, (x) => x * 2); console.log(a2);//[ 2, 4, 6, 8, 10 ] //这不比map好用?这不比map好用?!
-
Array.of()
//把参数转换成数组 console.log(Array.of(1, 2, 3, 4)); // [1, 2, 3, 4] console.log(Array.of(undefined)); //[undefined]
-
数组空位
const a1 = [, , , , ,]; console.log(a1.length); //5 console.log(a1); //[,,,,,] const options = [1,,,,5]; // map()会跳过空位置 console.log(options.map(() => 6)); // [6, undefined, undefined, undefined, 6] // join()视空位置为空字符串 console.log(options.join('-')); // "1----5"
-
数组索引
数组中元素的数量保存在length属性中,并且始终返回0或大于0的值重点来了:length不光是只读的,还可以通过修改它对数组末尾删除或者添加元素
let colors = ["red", "blue", "green"]; // 创建一个包含3个字符串的数组 colors.length = 2; alert(colors[2]); // undefined let colors = ["red", "blue", "green"]; // 创建一个包含3个字符串的数组 colors.length = 4; alert(colors[3]); // undefined let colors = ["red", "blue", "green"]; // 创建一个包含3个字符串的数组 colors[99] = "black"; // 添加一种颜色(位置99) alert(colors.length); // 100
数组最多可以包含4294967295个元素,基本满足开发需求
-
迭代器方法
- keys():返回数组索引。
- values():返回数组元素。
- entries():返回:索引,值。
const arr = ['test1','test2','test3','test4'] console.log([...arr.keys()]); //[ 0, 1, 2, 3 ] console.log([...arr.values()]); //[ 'test1', 'test2', 'test3', 'test4' ] console.log([...arr.entries()]); // [ [ 0, 'test1' ], [ 1, 'test2' ], [ 2, 'test3' ], [ 3, 'test4' ] ]
解构的方式获取键值对变的非常容易
for (const [idx, element] of arr.entries()){ console.log(idx); console.log(element); }
如果数组中某一项是null或undefined,则在join()、toLocaleString()、toString()和valueOf()返回的结果中会以空字符串表示
-
排序方法
- sort():默认情况升序排序数组,从小到大,而且sort是将每一项调用String()转换成字符串后排序。
const arr = [1,2,3,4,5,9,10,11,12,13,14,15] console.log(arr.sort()) //[1, 10, 11, 12, 13, 14, 15, 2, 3, 4, 5, 9]
默认方法排序不准确,正常情况下需要传参
- 断言函数(找到元素后不会再向下执行)
const arr = [ { name: "a", age: 18 }, { name: "b", age: 20 }, { name: "c", age: 22 }, { name: "d", age: 25 } ] console.log(arr.find(item => item.age < 22)) //{ name: 'a', age: 18 } console.log(arr.findIndex(item => item.age < 25)) //0
- 归并方法(reduce和reduceRight)
const arr = [1, 2, 3, 4, 5] let arrSum = arr.reduce((pre, cur, index, array) => { return pre + cur },15) console.log(arrSum); //30
-