ES6新特性P1

文章目录


一、ES6模块化

1、什么是模块化?

模块化是指将一个大的程序文件,拆分为许多小的文件,然后再将小文件组合起来。

2、为什么要编写模块化代码?

  • 防止命名冲突
  • 代码复用
  • 高维护性

3、JS的模块化规范有哪些?

  • commonJS
  • AMD
  • CMD
  • ES6模块化

4、ES6模块化

4.1、export命令用于规定模块的对外接口

暴露语法:

  • 分别暴露:export xxx
export function foo () {
  console.log("foo() module1.js")
}
export function bar () {
  console.log("bar() module1.js")
}
export let arr = [1, 2, 3, 4, 5, 6];
  • 统一暴露:export {xxx,yyy}
function fun1 () {
 console.log("fun() module2.js");
}
function fun2 () {
 console.log("fun() module2.js");
}
export { fun1, fun2 }
  • 默认暴露:export default{} 只能写一次
export default {//default只能写一次
  msg: "我是默认暴露",
  foo: function () {
    console.log(this.msg);
  }
}

4.2、import命令用于输入其他模块提供的功能

  • 语法:import xxx from ‘路径’
//引入其他的模块
//引入第三方库写在最前面
import $ from 'jquery';
import { foo, bar } from './module1';
import { fun1, fun2 } from './module2';
import module3 from './module3';

$('body').css('background', 'green')
foo()
bar()
fun1()
fun2()
module3.foo();

注意点:
若是引入多个模块是=时,有同名的需要用as起别名

5、commonJS模块化与ES6模块化的区别?

  • commonJS适用于node.js服务器端,而ES6浏览器端和服务器端都适用
  • 语法差异:CommonJS 模块使用require()和module.exports,ES6 模块使用import和export
  • commonJS是在运行时加载,而ES6模块化是在编译时就已经加载完毕了
  • CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。

二、let和const

let的特性

  • 具有块级作用域
  • 不能重复声明
  • 不存在变量提升
    //1、不能重复声明:
     let obj = "spylent";
     let obj = "疯兔"; //Uncaught SyntaxError: Identifier 'obj' has already been declared

    //2、块级作用域:
     {
       let obj1= "王天雄";
     }
     console.log(obj1); //Uncaught ReferenceError: obj1 is not defined

    //3、不存在变量提升
     console.log(a);
     let a = 1; //Uncaught ReferenceError: Cannot access 'a' before initialization

什么是块级作用域?
在ES6中被{}包裹起来的代码就是一个块,而{}中就形成了一个块级作用域,比如if(){}、for(……){}、……

const的特性

  • 声明时必须赋值
  • const声明的是常量,一旦赋值就不能再修改,但对于引用数据类型,只要不是修改引用地址就可以修改这个数据里的数据
  • 具有块级作用域
  • 不能重复声明
  • 不存在变量提升
    //1、一定要赋初始值
     const A;//Missing initializer in const declaration
    //2、一般常量使用大写:
    const CYM = "cym";
    //3、常量的值不能修改:
     CYM = 1;//Assignment to constant variable.
    //4、对于引用型数据类型内部数据的修改不算是对常量的修改,不会报错:
    const OBJ = {
      cym: "cym"
    }
    OBJ.cym = "wtx";

for和var一起使用与for和let一起使用的区别?

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>let实例</title>
  <style>
    .box {
      width: 100px;
      height: 50px;
      border: 1px solid black;
      margin: 5px 0;
    }
  </style>
</head>

<body>
  <div class="box"></div>
  <div class="box"></div>
  <div class="box"></div>
  <script>
    let boxes = document.getElementsByClassName("box");
    for (let i = 0; i < boxes.length; i++) {
      boxes[i].onclick = function () {
        boxes[i].style.background = "red";
        console.log(i);// 0 1 2
      }
    }
    // for (var i = 0; i < boxes.length; i++) {
    //   boxes[i].onclick = function () {
    //     boxes[i].style.background = "red";//报错 此时i = 3
    //   }
    // }
  </script>
</body>

</html>

为什么会发生上述情况?
var声明的i会成为全局变量,每次循环中使用的i都是同一个i,等到循环结束之后i就变为3了;
而用let声明的i,因为块级作用域的关系,每一次循环中使用的i都是新的变量
问?如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?
这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。

三、解构赋值

什么是解构赋值?

解构赋值就是可以从对象或者数组中按照一定模式提取值,赋值给变量;

对象解构赋值

对象的解构是先找到同名属性,然后再赋给对应的变量

let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"

let { baz } = { foo: 'aaa', bar: 'bbb' };
baz // undefined

数组解构赋值

数组的解构变量的取值是根据它的位置决定的;

    // 1、数组的元素是按次序排列的,变量的取值由它的位置决定;
    const arr = [2, "wtx", true, 1];
    const [a, b, c, d] = arr;
    console.log(a);//2
    console.log(b);//"wtx"
    console.log(c);//true
    console.log(d);//1

    // 2、解构嵌套数组,就是模式匹配,只要等号两边的层级结构相同,就可以拿到对应位置的值
    const arr = [2, [3, 4, [5, 6, 7, [8]]]];
    const [a, [b, c, [d, e, f, [g]]]] = arr;

    // 3、相同“模式”的不完全解构
    const [a, b, c] = [1, 2];//1,2,undefined
    const [a, b] = [1, 2, 3];//1,2
    const [a, b, ...c] = [1, 2, 3, 4, 5, 6];
    console.log(a);//1
    console.log(b);//2
    console.log(c);//[3,4,5,6]

    // 4、解构的默认值
    const [a = 1] = [];
    console.log(a);//1

可用于变量进行值的交换:

let x = 1;
let y = 2;
[x,y] = [y,x]

从函数中返回多个数:

function example() {
  return [1, 2, 3];
}
let [a, b, c] = example();

四、模板字符串

ES6引入新的声明字符串的方式:``(键盘tab键上面的反引号)
使用该方式可以在字符串中使用变量,语法形式为:${变量名}

let name = "spylent";
let str = `我的名字为${name}`
console.log(str)//我的名字为spylent

可以在字符串中直接换行

cosnt str = 
`<ul>
	<li></li>
</ul>
`

五、简化了对象写法

  • 在对象中可以直接写入变量和函数:
	let name = "spylent";
    let setName = function (name) {
      return this.name = name;
    }
    let obj = {
      name,
      setName,
      setAge (age) {
        return this.age = age;
      }
    }
    obj.setAge(3);
    console.log(obj.age);//3

六、允许函数参数赋初始值

具有默认值的参数,一般位置要靠后

    //1、函数参数默认值
     function fun (a, b, c = 2) {
       console.log(a + b + c);//5
     }
     fun(1, 2);
    //2、与解构赋值结合
    function fun1 ({ a, b, c = 4 }) {
      console.log(a);//2
      console.log(b);//hahah
      console.log(c);//1
    }
    fun1({
      a: 2,
      b: "hahah",
      c: 1
    })

七、函数扩展之rest参数

ES6 引入 rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
rest 参数就是一个真正的数组,数组特有的方法都可以使用;
rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。

    function fun (a, b, ...args) {
      console.log(a);
      console.log(b);
      console.log(args);
    }
    fun(1, 2, 3, 4, 5, 6, 7, 8, 9);

八、箭头函数

ES6 允许使用“箭头”(=>)定义函数。

1、箭头函数声明

let fun = ()=>{
	console.log("我是箭头函数")
}
fun()

2、箭头函数的简写形式

2.1、若是参数只有一个时,可以省略小括号

let fun = item=>{
	console.log("我是"+item)
}
fun("spylent")

2.1、当代码体只有一条语句时,且此时若是省略花括号return必须省略

let fun = ()=>{
	return "spylent"
}
//可简写为
let fun = ()=>"spylent"

如果箭头函数直接返回一个对象,需要为对象套上括号

// 报错
let getTempItem = id => { id: id, name: "Temp" };

// 不报错
let getTempItem = id => ({ id: id, name: "Temp" });

3、箭头函数的特点

3.1、箭头函数没有this,若是在箭头函数中使用了this,则该this指向声明箭头函数时的作用域中的this,是静态的,不会随着调用者的改变而改变

    let obj = {
      name: "spylent",
      age: 13
    }
    let fun = () => {
      console.log(this.name);
    }
    window.name = "wtx";
    fun();//wtx
    fun.call(obj);//wtx

3.2、箭头函数不能作为构造函数创建实例对象

let Fun = (name, age) => {
      this.name = name;
      this.age = age;
    }
let fun = new Fun("cym", 13);
console.log(fun);//Uncaught TypeError: Fun is not a constructor

3.3、箭头函数中没有arguments,但是可以通过rest参数获取参数

let fun = () => {
   console.log(arguments);
}
fun(1, 2, 3);//Uncaught ReferenceError: arguments is not defined

箭头函数和普通函数的区别?

  1. 表现形式不同
  2. 普通函数有arguments,箭头函数没有,但可以通过rest参数获取参数
  3. 普通函数有this,且会随着调用者不同而改变,箭头函数没有this,在其中使用this,则是指向声明箭头函数的当前作用域的this,且this值是静态的,不会再改变
  4. 普通函数可以作为构造函数创建实例,箭头函数不能作为构造函数创建实例
  5. 箭头函数不能用作生成器函数,也不能在其中使用yield关键字,而普通函数可以

九、扩展运算符

表现形式:...

扩展运算符的应用

数组的合并

    let arr1 = [1, 2, 3];
    let arr2 = ["cym", "wtx"];
    let arr3 = [...arr1, ...arr2];
    console.log(arr3);//[1, 2, 3,"cym", "wtx"]

数组的克隆(浅克隆:若是数组中含有引用类型,则克隆的是引用地址)

let arr1 = ['abc', 1, 2, 3, { name: 'cym' }];
let arr2 = [...arr1];
console.log(arr2);//[ 'abc', 1, 2, 3, { name: 'cym' } ]

将伪数组转化为真正的数组

    let boxes = document.getElementsByTagName("div");
    let arr = [...boxes];
    console.log(arr);

十、对象方法的扩展

Object.is():判断两个值是否完全相等

    console.log(Object.is(112, 112));//true
    console.log(Object.is(NaN, NaN));//true
    console.log(NaN === NaN);//false

Object.assign():对象的合并(若是两个对象中含有相同的属性,则后者会覆盖前者的属性值)

const obj1 = {
  name: "spylent",
  age: 13,
  phone: 13737083879,
  address: "dsjaibfcaweujdc"
}
const obj2 = {
  name: "疯兔",
  age: 15,
  phone: 1328473623,
  gender: "男"
}
console.log(Object.assign(obj2, obj1));
//{name: 'spylent',age: 13,phone: 13737083879,gender: '男',address: 'dsjaibfcaweujdc'}

Object.getOwnPropertyDescriptor():返回某个对象属性的描述对象

const obj = {
  foo: 123,
  get bar() { return 'abc' }
};

Object.getOwnPropertyDescriptors(obj)
// { foo:
//    { value: 123,
//      writable: true,
//      enumerable: true,
//      configurable: true },
//   bar:
//    { get: [Function: get bar],
//      set: undefined,
//      enumerable: true,
//      configurable: true } }

Object.setPrototypeOf():用来设置一个对象的原型对象、Object.getPrototypeOf():用来获取一个对象的原型对象

const school = {
  name: "啊啊啊"
}
const citys = {
  xiaoqu: ["北京", "上海"]
}
Object.setPrototypeOf(school, citys);
console.log(Object.getPrototypeOf(school));//{ xiaoqu: [ '北京', '上海' ] }
console.log(school);//{ name: '啊啊啊' }

Object.keys(),Object.values(),Object.entries()

都会返回一个数组

var obj = { foo: 'bar', baz: 42 };
Object.keys(obj)
// ["foo", "baz"]
const obj = { foo: 'bar', baz: 42 };
Object.values(obj)
// ["bar", 42]
const obj = { foo: 'bar', baz: 42 };
Object.entries(obj)
// [ ["foo", "bar"], ["baz", 42] ]

Object.fromEntries()

Object.fromEntries()方法是Object.entries()的逆操作,用于将一个键值对数组转为对象。
该方法的主要目的,是将键值对的数据结构还原为对象,因此特别适合将 Map 结构转为对象。

Object.fromEntries([
  ['foo', 'bar'],
  ['baz', 42]
])
// { foo: "bar", baz: 42 }

十一、数组方法的扩展

Array.from()、Array.of()

from方法就是可以将两类对象转为数组:类数组对象以及可迭代对象(set/map)

let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
};
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

Array.from('hello')
// ['h', 'e', 'l', 'l', 'o']

let namesSet = new Set(['a', 'b'])
Array.from(namesSet) // ['a', 'b']

of方法是为了弥补数组构造函数Array()的不足

let arr = new Array(5)
console.log(arr)//[ <5 empty items> ]
console.log(arr[0])//undefined
let arr1 = Array.of(5)
console.log(arr1)//[ 5 ]

find(),findIndex(),findLast(),findLastIndex()

  • find():用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined。
[1, 5, 10, 15].find(function(value, index, arr) {
  return value > 9;
}) // 10
  • findIndex():返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1
[1, 5, 10, 15].findIndex(function(value, index, arr) {
  return value > 9;
}) // 2

这两个方法都可以发现NaN,弥补了数组的indexOf()方法的不足

  • findLast()和findLastIndex(),从数组的最后一个成员开始,依次向前检查,其他都保持不变
const array = [
  { value: 1 },
  { value: 2 },
  { value: 3 },
  { value: 4 }
];

array.findLast(n => n.value % 2 === 1); // { value: 3 }
array.findLastIndex(n => n.value % 2 === 1); // 2

fill()

const array = [1, 2, 3, [4, 5]]
array.fill("spyelnt", 0, 2)
console.log(array)//[ 'spyelnt', 'spyelnt', 3, [ 4, 5 ] ]
const array1 = [1, 2, 3, [4, 5]]
array1.fill("spyelnt", 0, 4)
console.log(array1)//[ 'spyelnt', 'spy

entries(),keys() 和 values()

keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历
都会返回一个迭代器对象

for (let index of ['a', 'b'].keys()) {
  console.log(index);
}
// 0
// 1

for (let elem of ['a', 'b'].values()) {
  console.log(elem);
}
// 'a'
// 'b'

for (let [index, elem] of ['a', 'b'].entries()) {
  console.log(index, elem);
}
// 0 "a"
// 1 "b"

includes()

弥补了indexOf无法发现NaN的缺陷;
该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。

[1, 2, 3].includes(2)     // true
[1, 2, 3].includes(4)     // false
[1, 2, NaN].includes(NaN) // true

[1, 2, 3].includes(3, 3);  // false
[1, 2, 3].includes(3, -1); // true

flat(),flatMap()

  • flat() :用于将数组扁平化,默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,可以将flat()方法的参数写成一个整数,表示想要拉平的层数
[1, 2, [3, 4]].flat()
// [1, 2, 3, 4]

[1, 2, [3, [4, 5]]].flat(2)
// [1, 2, 3, 4, 5]
//如果不管有多少层嵌套,都要转成一维数组,可以用Infinity关键字作为参数
[1, [2, [3]]].flat(Infinity)
// [1, 2, 3]
  • flatMap()方法:对原数组的每个成员执行一个函数(相当于执行Array.prototype.map()),然后对返回值组成的数组执行flat()方法。该方法返回一个新数组,不改变原数组。
    flatMap()只能展开一层数组
[2, 3, 4].flatMap((x) => [x, x * 2])
// [2, 4, 3, 6, 4, 8]

copyWithin()

在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。

const array = [1, 2, 3, [4, 5], 11, 33];
console.log(array.copyWithin(0, 3, -2));//[ [ 4, 5 ], 2, 3, [ 4, 5 ], 11, 33 ]
//上述代码意思是将索引下标为3的元素到-2往前的一个元素为止,也就是只复制[4,5],
//覆盖0号位的元素

[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]
//上面代码表示将从 3 号位直到数组结束的成员(4 和 5),复制到从 0 号位开始的位置,结果覆盖了原来的 1 和 2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值