ES6面试的自我总结

1.var、let、const的区别

1.var 可以变量提升,const、let不存在变量提升。
	(1)var 代码
	console.log(a); // undefiend
	var a = 100;
	(2)let、const 代码
    console.log(b); // Cannot access 'b' before initialization
	const/let b = 100;
2.var 不存在暂时性死区,const、let存在暂时性死区,只有等声明的那一行代码出现,才可以获取该变量的值。例子同上。
3.var 不存在块级作用域,const、let存在块级作用域。
	(1)
	{
        var a = 100;
     }
	console.log(a); // 100
	(2)
	{
        let/const b = 100;
    }
	console.log(b); // b is not defined
4.var 可以重复生命,const、let不允许重复声明。
	(1) 
		var a = 100;
		var a = 10;
		console.log(a); // 10
	(2)
		const/let b = 100;
		const/let b = 1000;
		console.log(b); // Identifier 'b' has already been declared
5.var 、let可以修改变量的值,const不能改变。
	(1)	
		var/let a = 100;
	    a = 10;
		console.log(a); // 10
	(2)
		const b = 100;
		b = 1000;
		console.log(b); // Uncaught TypeError: Assignment to constant variable

2. ES6中新增的Set、Map两种数据结构怎么理解?

1.共同点:集合、字典都可以存储不重复的值。
2.不同点:集合是以[值,值]的形式存储元素,字典是以[键,值]的形式存储。
3.Set只有值,元素不可重复且自动排序,Map是以键值对的方式存储。
4.例子
	(4.1)
		const objSetList = 
              [
                  {
                      id : 1,
                      name: "skam"
                  },
                  {
                      id : 2,
                      name: "skam2"
                  }
              ];
		const objMapList = 
              [
                  ['key', 'value'],
                  ['任意类型', { id: 1, name: "skam" }]
              ];
		const SetList = new Set(objSetList);
		const MapList = new Map(objMapList);
		console.log(SetList); // [[entries]] 下面的第0项 -> value: { id : 1, name : "skam" },
							// 第1项 -> vlaue: { id : 2, name : "skam2" }
		console.log(MapList); // [[entries]] 下面的第0项 -> { key : "key", value: "value" },
							// 第1项 -> { key: "任意类型", value : { id : 1, name : "skam" } }

3.怎么理解ES6中 Promise的?使用场景有哪些?

1.是一种异步编程方式,用来解决回调地狱,优点(链式操作减低了编码难度、代码可读性明显增强)
2.三种状态(peeding、fulfilld、rejected)和种实例方法(then、catch、finally)
	const Promise = function () {
            new Promise((resolve, reject) => {
            axios.get(url,...)
        }).then(res => {  // 当请求成功后,会把返回的数据当作参数(res), 然后打印输出。
            console.log(res);  
        }).catch(err = > {
		   console.log(err);  // 当请求失败后,会把请求失败的原因当作参数(err), 然后打印输出。
        }).finally(() => {
            console.log("不管状态如何,我都会执行")  // 不管请求是否成功,都会打印这句话
        })
    }
	Promise();
3.Promise.all() -> const p = Promise.all([p1, p2, p3]);  
	接受一个参数(数组),只有数组中所有都resolve都通过了, p.then()才会执行,只要有一个reject, 改错误就会执行单个错误请求的
	reject, 不会触发Promise.all()的catch方法。
4.Promise.race() -> 同上
	只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变,率先改变的 Promise 实例的返回值则传递给p的回调函数。
5.使用场景?
	(5.1)图片的加载。
    (5.2)图片的请求超时

4.怎么理解ES6中 Generator的?使用场景有哪些?

1.是一种异步编程解决方案,执行Generator函数会返回一个遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。
2.特征:
	(2.1)function关键字与函数名之间有一个星号
    (2.2)函数体内部使用yield表达式,定义不同的内部状态
    (2.3)函数执行返回一个generater对象,函数体里面任何代码不会执行。
    (2.4)每次执行next(),遇到yield就会终止,再次next直到遇到return为止,把return后语句返回,如果没有return,value为			  undefnied。
    (2.5)将异步任务同步化
3.使用
	(3.1)
		function* generater(b){
            let a = 100;
            console.log(a * 1);
            yield console.log(a * 1);
            yield console.log(a * 1);
            return console.log(a * 4);
        }

        const y = generater()
        console.log(y); // generater对象 
        console.log(y.next()); // 100 200  done: false
        console.log(y.next()); // 300   done: false
        console.log(y.next()); // 400   done: false
	    console.log(y.next())  // done: true  当done为true时,相当于改函数完整执行一次,后面多次next返回相同结果。
	(3.2)
        function* foo() {
          yield 1;
          yield 2;
          yield 3;
          yield 4;
          yield 5;
          return 6;
        }

        for (let v of foo()) {
          console.log(v);	// 1 2 3 4 5
        }
4.使用场景
	(4.1)Generator是异步解决的一种方案,最大特点则是将异步操作同步化表达出来
            function* loadUI() {
              showLoadingScreen();
              yield loadUIDataAsynchronously();
              hideLoadingScreen();
            }
            var loader = loadUI();
            // 加载UI
            loader.next()
            // 卸载UI
            loader.next()  // 这列加载UI和卸载UI就相当于同步代码, 其实内部是异步请求的。
	(4.2)利用Generator函数,在对象上实现Iterator接口
                function* iterEntries(obj) {
                  let keys = Object.keys(obj);
                  for (let i=0; i < keys.length; i++) {
                    let key = keys[i];
                    yield [key, obj[key]];
                  }
                }

                let myObj = { foo: 3, bar: 7 };

                for (let [key, value] of iterEntries(myObj)) {
                  console.log(key, value);	// foo 3	// bar 7
                }

5. symbol 有什么用处?应用场景?

1.新的原始数据类型Symbol,表示独一无二的值。
2.细节
	let obj = {
		[Symbol("name")]: "一斤代码",
		age: 18,
		title: "Engineer",
	}

//(2.1) 使用symbol作为对象属性名不被Object.key等方式访问
//(2.2) 使用JSON.stringify()将对象转换成JSON字符串,Symbol属性会被排除在外
//(2.3) 获取Symbol方式定义的对象属性
            Object.getOwnPropertySymbols(obj);//[Symbol(name)]
            Reflect.ownKeys(obj);// ['age', 'title', Symbol(name)]
3.应用场景
	使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突,那么就使用
    Symbol创建一个独一无二的对象名。

6.箭头函数和普通函数有啥区别?箭头函数能当构造函数吗?

1.箭头函数与普通函数的区别
	(1)语法更加简洁、清晰
	(2)箭头函数不会创建自己的this
		(2.1)官方解释 箭头函数不会创建自己的this,所以它没有自己的this,它只会从自己的作用域链的上一层继承this。
		(2.2)箭头函数中this的指向在它被定义的时候就已经确定了,之后永远不会改变
	(3)箭头函数继承而来的this指向永远不变
	(4).call()/.apply()/.bind()无法改变箭头函数中this的指向
	(5)箭头函数没有自己的arguments
	(6)箭头函数没有原型prototype
	(7)箭头函数不能用作Generator函数,不能使用yeild关键字
2.箭头函数能当构造函数吗?
	构造函数的new都做了些什么?
		(1)JS内部首先会先生成一个对象
		(2)再把函数中的this指向该对象
		(3)然后执行构造函数中的语句
		(4)最终返回该对象实例
	因为箭头函数没有自己的this,它的this其实是继承了外层执行环境中的this,且this指向永远不会随在哪里调用、被谁调用而改变,所	以箭头函数不能作为构造函数使用,或者说构造函数不能定义成箭头函数,否则用new调用时会报错!

7.common.js和es6中模块引入的区别?

1.CommonJS模块输出的是一个值的拷贝	<-->	ES6模块输出的是值的引用
2.CommonJS模块是运行时加载	<-->	ES6模块是编译时输出接口
3.CommonJs是单个值导出	<-->	ES6 Module可以导出多个
4.CommonJs是动态语法可以写在判断里	<-->	ES6 Module静态语法只能写在顶层
5.CommonJs的this是当前模块	<-->	ES6 Module的this是undefined
6.CommonJS 模块的require()是同步加载模块	<-->	ES6 模块的import命令是异步加载,有一个独立的模块依赖的解析阶段

8.谈谈 Object.defineProperty 与 Proxy 的区别

1.Object.defineProperty(obj, prop, descriptor)
	(1.1) 不能监听数组的变化 Vue2.x 中解决数组监听的方法是将能够改变原数组的方法进行重写实现(比如:push、 pop、shift、			  unshift、splice、sort、reverse)
	(1.2) 必须遍历对象的每个属性	-->		通过 Object.keys() 来实现
	(1.3) 必须深层遍历嵌套的对象	-->		通过递归深层遍历嵌套对象,然后通过 Object.keys() 来实现对每个属性的劫持
2.Proxy
	(2.1) Proxy 针对的整个对象,Object.defineProperty 针对单个属性,这就解决了 需要对对象进行深度递归(支持嵌套的复杂对象		  劫持)实现对每个属性劫持的问题
	(2.2) Proxy 解决了 Object.defineProperty 无法劫持数组的问题
	(2.3) 比 Object.defineProperty 有更多的拦截方法,对比一些新的浏览器,可能会对 Proxy 针正对性的优化,有助于性能提升

9. object.assign和扩展运算法是深拷贝还是浅拷贝,两者区别是什么?

1. 都是浅拷贝。
2. 区别
	(2.1)Object.assign()方法接收的第一个参数作为目标对象,后面的所有参数作为源对象。然后把所有的源对象合并到目标对象中。它		 	会修改了一个对象,因此会触发 ES6 setter。
	(2.2)扩展操作符(…)使用它时,数组或对象中的每一个值都会被拷贝到一个新的数组或对象中。它不复制继承的属性或类的属性,但是			  它会复制ES6的 symbols 属性

10. ES6有哪些新特性?

1.解决原有语法上的一些不足
	比如let 和 const 的块级作用域
2.对原有语法进行增强
	比如解构赋值、展开运算符(...)、参数默认值、模板字符串(``)
3.全新的对象、全新的方法、全新的功能
	比如promise、proxy、object的assign、is
4.全新的数据类型和数据结构
	比如symbol、set、map

11. 说说对 ES6 中rest参数的理解

1.什么是rest参数 --> function fn(...rest) {}   // ...rest 就是rest参数
2.举例
	function fn(...rest) {
        console.log(rest) // [1, 2, 3, 4]
        console.log(...rest) // 1 2 3 4
        console.log(rest.length) // 4
    }
	fn(1, 2, 3, 4)
3.rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。
	function fn2(...rest, a) {}  // 会报错
posted @ 2022-04-29 17:51  SKa-M  阅读(112)  评论(0编辑  收藏  举报