关于Es6的面试一些知识点,附答案
答:不同点:
(1)不允许声明提升
(2)不允许重复声明
(3)不覆盖全局变量
2,请说下const的特点
答:a,const一般只用于声明常量,声明的同时会直接初始化
b,声明的常量不能修改,否则会报错
c,必须遵守先声明后使用,否则报错
d,声明对象的时候,对象的属性名和属性值都可以添加,修改,却不能重新指向另一个对象,不能重写对象
3,扩展运算符(...)有那些用途?
答:a,替代函数apply()的方法
b,简化函数调用时传递实参的方式
c,处理数组和字符串
4,剩余参数有什么作用?
答:允许我们将一个不定数量的参数表示为一个数组。
限制:函数声明时必须放在最后
不能在字面量setter中方法中声明,因为setter只会接收一个参数,而剩余参数不会限制参数的数量
5,什么是解构?
答:解构是一种赋值语法,可从数组中提取元素或从对象中提取属性,将其值赋给对应的变量或者另一个对象的属性,解构的目的是简化提取数据的过程,增强代码的可读性,有两种解构语法,分别为数组解构和对象解构,两者的区别在于解构赋值语句的左侧,前者是数组字面量,后者是对象字面量,例如:
var arr=[1,2], obj={a:3,b:4}, x,y,a,b; x=arr[0]; y=arr[1]; a=obj.a; b=obj.b; var[x,y]=[1,2]; //数组解构 var {a,b}={a:3,b:4} //对象解构
6,如果忽略声明关键字,那么在运行对象解构的时候为何要用圆括号包裹赋值表达式,如下所示:({a,b}={a:3,b:4})
答:之所以要用圆括号包裹,是因为表达式左侧的花括号会被解析成代码块而不是对象字面量,如果把代码块和等号运算符放在一行,那么就会报语法错误,当执行解构语句时,如果等号左侧的变量或者对象属性没有从右侧找到对应的数组元素或对象属性,那么就会被赋为undefined
7,如何利用数组解构交换变量?
答:在数组解构时,解构会按照顺序作用于数组的元素上,也就是说,变量或对象属性要取谁的值与他所在的位置有关,例如
[x,y]=[1,2] console.log(x,y) // 1,2 [y,x]=[1,2] console.log(x,y) //2,1
8,执行[,,z]=[1,2,3]后,z的值为?
答:3
9,执行[x,...y]=[1,2,3]后,x的值为?y的值为?
答:x:1,y=[2,3]
10,执行({a:e,a:f}={b:5,a:6})后,e的值为?f的值为?
答:e=6,f=6
11,执行({a,b=2}={a:1,b:null})后,b的值为?
答:b=null
12,什么是模板字面量?
答:模板字面量是一种能够嵌入表达式的格式化字符串,有别于普通的字符串,用倒引号(``),不是单引号也不是双引号。模板字面量包含特定形式的占位符,${expression}
13,模板字面量有那些局限?
答:
14,ES6是否扩展了对象字面量中的属性名?
15,请谈谈你对Symbol的理解?
答:Symbol(符号),符号可以像字符串那样作为对象的属性名,只是他有唯一的特点,可以避免属性名之间的冲突。
a,创建:符号没有字面量形式,只能通过Symbol()函数创建,该函数有一个可选的参数,只是用来描述当前符号,除了便于阅读外,没有其他用途,由此可知,即使两个符号描述相同也不能画等号,Symbol()不是构造函数,所以不能和new运算符一起使用,否则会抛出类型错误
b,类型转化:符号在类型转换的时候并不灵活,它无法与数字或字符串进行运算,也无法显示转换成数字,不过,符号可以显示转换成字符串或布尔值
c,全局共享:ES6会在内部维护一张全局符号注册表,通过Symbol.for()方法,可以登记指定的符号,使其变成全局有效的符号,从而达到全局共享,该方法只接受一个参数,
d,属性名:有三种赋值方法,第一种,用方括号,不能用点号,因为点号后面会被识别成字符串而不是符号
var sym=Symbol("name"), obj={}; obj[sym]="strick" obj.sym="strick" console.log(obj) //{Symbol(name): "strick", sym: "strick"}
第二种,在创建对象字面量的时候,用计算属性名的方式(即属性名被方括号包裹)为其赋值,
obj = { [sym]: "freedom" };
第三种,调用Object.defineProperty()或者Object.defineProperties()方法来为符号属性赋值
Object.defineProperty(obj, sym, { value: "justice" });
注意,符号属性是不可枚举的,既不能被for-in循环遍历,也不能被Object.keys(),Object.getOwnPropertyNames()方法读取到,但是可以通过Object.getOwnPropertySymbols()方法获取对象的符号属性
obj = { [sym]: "freedom", age: 28 }; Object.keys(obj); //["age"] Object.getOwnPropertyNames(obj); //["age"] Object.getOwnPropertySymbols(obj); //[Symbol(name)]
16,如何理解内置符号?
答:内置符号,ES6提供一些内置符号,也叫作知名符号,他们暴露了语言在内部逻辑,允许开发人员修改或拓展规范锁描述的对象或行为,每一个内置符号对应Symbol对象的一个属性。例如Symbol.hasInstance、Symbol.iterator等
下面会给出4个内置符号的示例,分别是hasInstance、isConcatSpreadable、match和toStringTag。
let digit = { [Symbol.hasInstance](number) { return !(number % 2); //判断数字是否为偶数 } }; 1 instanceof digit; //false 2 instanceof digit; //true let arr1 = [3, 4]; [1, 2].concat(arr1); //[1, 2, 3, 4] let arr2 = [3, 4]; arr2[Symbol.isConcatSpreadable] = false; //禁止展开 [1, 2].concat(arr2); //[1, 2, [3, 4]] let regex = { [Symbol.match](str) { return str.substr(0, 10); } }, message = "My name is strick"; message.match(regex); //"My name is" let people = { [Symbol.toStringTag]: "People" }; people.toString(); //"[object People]"
17,[...[..."..."]].length返回的结果为?
18,如何导出模块成员?
答:一个模块就是一个独立的javascript文件,如果要读取文件内的变量,函数或类,那么必须先将他们用export关键导出,因为他们默认是私有的,导出的方式有多种
a,将关键字放在变量,函数等声明之前,常被称为命名导出,注意,命名导出的变量或函数都需要有名称,否则会抛出语法错误
export let name = "strick"; export function getName() { return "strick"; } export class people { getName() { return "strick"; } }
b,命名导出,只是形式不同,声明和导出分为两步,要导出的标识符会用花括号包裹起来
let age = 28; function getAge() { return 28; } export { age, getAge }; export { age as myAge, getAge as getMyAge }; //设置别名
c,用于导出模块的全部或部分成员,此时需要包含四个部分,分别是导出标识符,模块路径,以及两个关键字exprot和from,如果要到处全部,导出符用星号(*),如果是部分的话,导出符可以像第二种命名导出那么写。注意,模块路径不能简写,需要以“/”、“./”或“../”开头,千万不要因为文件在同级就省略相应的字符。
import { name, age } from "./1.js";
export { name, age };
19,如何导入模块成员?
答:如果想导入某个模块成员,可以使用import关键字,和导出类似,也包含四个部分,导入标识符,模块路径,以及两个关键字import和from,模块路径不能简写
import * as people from "./1.js"; //导入全部 import { name, age } from "./1.js"; //导入部分 import { getAge as getMyAge } from "./1.js"; //导入部分并设置别名
a,只读变量,用import导入的变量都是只读的,相当于为他添加const限制,如果在模块中为其重新赋值,那么必会引起类型错误,想要更新导入的变量,有一种间接的办法
export let name = "strick"; export function setName(str) { name = str; }
然后在另一个模块中导入刚刚的两个成员,接着将新的name值通过setName()函数传入到1.js模块内部进行更新
import { name, setName } from "./1.js"; console.log(name); //"strick" setName("freedom"); console.log(name); //"freedom"
b,成员提升,从模块中导入的成员默认会被提升至当前模块作用域的顶部,类似声明提升,因此下面的写法是正确的
import { name, setName } from "./1.js"; console.log(name); //"strick" setName("freedom"); console.log(name); //"freedom"
c,简洁导入,import语句中的导入标识符和from的关键字都是可选的,但要注意,只有当两者一起省略时语句才能被正确的执行
import "./jquery.js";
由于import加载的模块都会被执行一次,因此可以用上面这种简洁导入来实现脚本的预加载。而这些脚本既可以是自己封装的代码段,也可以是jQuery、Zepto等第三方类库。
20,模块默认值是指什么?
答:ES6中的default关键字可以指定模块的默认值,即为模块指定默认的导出和导入。
a,默认导出,一个模块只能存在一个默认导出,下面会列出四种写法
let name = "strick"; export default name; //写法一 export default function getName() { //写法二 return "strick"; } export default function() { //写法三 return "strick"; } export { name as default }; //写法四
b,默认导入
import name from "./1.js"; //写法一 import name, { age } from "./1.js"; //写法二 import name, * as people from "./1.js"; //写法三 import { default as myName } from "./1.js"; //写法四
21,代码模块化有那些限制?
答:a,模块路径,由于ES6中的模块被设计成了静态,因此需要在编译阶段就明确模块之间的依赖关系而不是在运算过程中动态计算
b,作用域,export和import语句都是静态的,无法动态导入和导出,因此只能出现在模块的顶层作用域中,而不能出现在块级或函数作用域中
c,标识符,导出和导入语句中的标识符如果重复,那么也会引起语法错误,如下所示。
export { name, name } from "./1.js";
import { name, name } from "./1.js";
22,Number.isFinite(null)返回结果为?
答:false
23,请谈谈你对Unicode的理解?
答:ES6为Unicode字符提供了一种新形式,只需把码位用花括号包裹,就能支持辅助平面中的字符。下面使用了新形式来描述字符“𠮳”。
let word3 = "\u{20BB3}"; console.log(word3); //"𠮳"
24,什么叫Unicode标准化?
答:Unicode标准化也叫Unicode规范化或Unicode正规化,可将字符串转化为指定的字节序列,统一表现形式,以及确定字符之间的等价性,
25,"My name is strick".includes("name")返回的结果为?
26,正则表达式的u标志有什么作用?
27,正则表达式的y标志有什么作用?
28,如何判断一个字符是由两个编码单元组成的?
29,Object.is()有什么功能?
答:比较两个值是否严格相等
30,如何使用Object.assign()?
答:浅复制。
- 为对象添加属性
- 为对象添加方法
- 克隆对象
- 合并多个对象
- 为属性指定默认值