当你在面试中被问到ES6有哪些新技术

62 阅读6分钟

一、let和const

// 1.var 声明变量存在变量提升,let和const不存在变量提升
console.log(a) // undefined ==> a已声明还未赋值,默认得到undefined值
console.log(b) // 报错:b is not defined 找不到b这个变量
console.log(c) // 报错:c is not defined 找不到c这个变量
var a = 100;
let b = 10;
const c = 10;

// 2.let和const只能在块作用域里访问
if(1){
    var a = 100;
    let b = 10;
    const c = 1;
}
console.log(a); // 100
console.log(b)  // 报错:b is not defined  ===> 找不到b这个变量
console.log(c)  // 报错:c is not defined  ===> 找不到c这个变量

// 3.同一作用域下let和const不能声明同名变量,而var可以
var a = 100;
console.log(a) // 100
var a = 10;
console.log(a) // 10

let a  = 100;
let a =10; // 报错:Identifier 'a' has already been declared  ===> 标识符a已经被声明了。

// 4.const定义常量,而且不能修改,但是在定义的对象是对象时对象属性值可以改变
const a = 2;
a = 3;
console.log(a) // 报错

const person = {
    name:"make",
    sex:"男"
}

person.name = 'test'
console.log(person.name) //运行发现控制台没有报错,且person.name被成果更改。这是因为对象是引用类型的, person中保存的仅是对象的指针,而修改对象的属性不会改变对象的指针,所以这种情况就会修改成果。也就是说const定义的引用类型只要指针不发生改变,都是被允许的。

// 接下来我们试着修改一下指针,让person指向一个新对象,最后果然报错

const person = {
  name : 'make',
  sex : '男'
}

person = {
  name : 'test',
  sex : '男'
}
console.log(person.name)  //控制台报错

// 5.小结
1.var定义的变量,变量提升,没有块的概念,可以跨块访问。
2.let定义的变量,只能在块作用域里访问,不能声明同名变量
3.const用来定义常量,使用时必须初始化(必须赋值),不能声明同名变量,只能在块作用域里访问,而且不能修改,但是在定义的对象是对象属性值时可以改变。
4.他们都不能跨函数访问。

二、Symbol

Symbol是ES6中引入的一种新的基本数据类型,用于表示一个独一无二的值,不能与其他数据类型进行运算,它是JS中的第七种数据类型,与undefined、null、number、string、boolean、object并列。

三、模板字符串

在ES6之前,处理模板字符串通过“\”和“+”来构建模板 在ES6之后,用${}来界定,用反引号(``)直接敲定

字符串新方法
includes判断字符串是否包含参数字符串,返回boolean值
startWith / endWith,判断字符串是否以参数字符串开头或结尾,返回boolean值。这两个方法可以有第二个参数,一个数字,表示开始查找的位置。
let str = 'blue,red,orange,white';
str.includes('blue') // true
str.startsWith('blue') // true
str.endsWith('blue') // false

//repeat()方法按指定次数返回一个新的字符串。
console.log('hello'.repeat(2));   //'hellohello'

// padStart()/padEnd(),用参数字符串按给定长度从前面或后面补全字符串,返回新字符串。
let arr = 'hell';
console.log(arr.padEnd(5,'o'));  //'hello'
console.log(arr.padEnd(6,'o'));  //'helloo'
console.log(arr.padEnd(6));  //'hell  ',如果没有指定将用空格代替

console.log(arr.padStart(5,'o'));  //'ohell'

四、解构表达式

解构赋值是对赋值运算符的扩展。它是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。字符串、以及ES6新增的Map和Set都可以使用解构表达式。

// 1.数组解构
let [a,b,c] = [1,2,3];
console.log(a,b,c) // 1,2,3

let [a,b,c] = [1,,3];
console.log(a,b,c);    //1,undefined,3

let [a,,b] = [1,2,3];
console.log(a,b);//1,3

let [a,..b] = [1,2,3];  //...是剩余运算符,表示赋值运算符右边除第一个值外剩余的都赋值给b
console.log(a,b);//1,[2,3]

// 2.对象解构
let obj = {
    name:"ren",
    age:12,
    sex:"male"
}

let {name,age,sex} = obj;
console.log(name,age,sex) // 'ren' 12 'male'

let { name: myName, age: myAge, sex: mySex } = obj; //自定义变量名
console.log(myName, myAge, mySex); //'ren' 12 'male'

五、对象方面

Map和Set Map和Set都属于ES6新增加的对象 Map:Map对象用于保存键值对,任何JS支持的值都可以作为一个键(key)或者一个值(value)。与对象不同的是 1.Object的值只能是字符串或者ES6的Symbol值,而Map可以是任何值 2.Map对象有一个size属性,存储了键值对的个数而Object对象没有任何类似属性

let myMap = new Map([['name','ren'],['age',12]]);
console.log(myMap);  //{'name'=>'ren','age'=>12}

myMap.set('sex','male');
console.log(myMap);  //{'name'=>'ren','age'=>12,'sex'=>'male'}
console.log(myMap.size);  //3

myMap.get('name');  //'ren'
myMap.has('age');  //true
myMap.delete('age');  //true
myMap.has('age');  //false
myMap.get('age');  //undefined

Set 可以理解为后端的Set集合对象 Set对象和Map对象类似,但它存储的不是键值对。类似数组,它的每个元素都是唯一的。

let mySet = new Set([1,2,3]);//里面要传一个数组,否则会报错
console.log(mySet);  //{1,2,3}

mySet.add(4);
console.log(mySet);  //{1,2,3,4}

mySet.delete(1);  //true
mySet.has(1);  //false
console.log(mySet);  //{2,3,4}

利用Set对象唯一性的特点,可以轻松实现数组的去重
let arr = [1,1,2,3,4,4];
let mySet = new Set(arr);
let newArr = Array.from(mySet);
console.log(newArr);  //[1,2,3,4]

六、函数方面

箭头函数

1.相比普通函数,箭头函数更加简洁而
// 普通函数
function add(num){
  return num + 10
}
// 箭头函数
const add = (num) => {
  return num + 10
}

2.箭头函数不绑定this,会捕获其所在上下文的this,作为自己的this(需要注意的是,箭头函数的外层如果有普通函数,那么箭头函数的this就是这个外层的普通函数的this,箭头函数的外层如果没有普通函数,那么箭头函数的this就是全局变量)
// 箭头函数外层有普通函数
let obj = {
  fn:function(){
    console.log('我是普通函数',this === obj) // true
    return () => {
      console.log('我是箭头函数',this === obj) // true
    }
  }
}
// 箭头函数外层无普通函数
let obj = {
  fn:()=>{
    console.log(this === window)
  }
}
console.log(obj.fn()) // true

3.箭头函数是匿名函数,不能作为构造函数,不能使用new命令,否则抛出错误
let fn = () => {}
let newFn = new fn() // fn is not a constructor

4.箭头函数不绑定arguments,取而代之用rest参数解决,同时没有supernew.target(箭头函数没有argumentssupernew.target的绑定,这些值由外围最近一层非箭头函数决定)
let fn = () => {
  console.log(arguments)
}
fn() // 报错 arguments is not defined
function fn(){
  let f = () => {
     console.log(arguments)
  }
  f();
}
fn(1,2,3) 

5.使用call、apply、bind并不会改变箭头函数中的this指向
当对箭头使用call或apply方法时,只会传入参数并调用函数,并不会改变箭头函数中this的指向,当对箭头函数使用bind方法时,只会返回一个预设参数的新函数,并不会改变这个新函数的this指向
window.name = "window_name";

let f1 = function () {
return this.name;
};
let f2 = () => this.name;

let obj = { name: "obj_name" };

console.log(f1.call(obj));  //obj_name
console.log(f2.call(obj));  // window_name
console.log(f1.apply(obj)); // obj_name
console.log(f2.apply(obj)); // window_name
console.log(f1.bind(obj)());  // obj_name
console.log(f2.bind(obj)());  // window_name

6.箭头函数没有原型对象prototype这个属性,由于不可以通过new关键字调用,所以没有构建原型的需求,所以箭头函数没有prototype这个属性
let fn = () => {}
console.log(fn.prototype) // undefined

7.不能使用yield关键字,不能用作Generator函数

七、class类

class作为对象的模板被引入ES6,你可以通过class关键字定义类。class的本质依然是一个函数 类的继承:类的继承通过extends关键字实现

八、promise

这个需要单开一节来讲

九、导入和导出

1.导入 ES6中使用关键字import导入模块(文件) 2.导出 ES6中通过export和export default导出模块 模块化的优点:1.防止命名冲突。2.可复用性强