1.基本包装类型(问:为什么'1'.toString()可以被调用)
基本类型和引用类型的值:
- ES6变量中包含两种不同的数据类型:基本类型值和引用类型值;
- 基本类型值:Null、Undefined、Boolean、Number、String、BigInt、Symbol;
- 引用类型值:Object(普通对象-Object,数组对象-Array,正则对象-RegExp,日期对象-Date,数字函数-Math,函数对象-Function);
- 注: 引用类型的值是保存在内存中的对象。与其他语言不同,JavaScript 不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。为此,引用类型的值是按引用访问的。
基本包装类型(答):
- 为了便于操作基本类型值,ECMAScript 还提供了3个特殊的引用类型Boolean、Number、String.这些类型与本章介绍的其他引用类型相似,但同时也具有与各自的基本类型相应的特殊行为。实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而让我们能够调用一些方法来操作这些数据。
var s1 = 'hello world';
s2 = s1.toString();
-
代码解析:
- 1.创建String类型的实例;
- 2.调用该实例的方法;
- 3.离开销毁实例;
基本包装类型与引用类型的区别:
-
对象的生命期不同:
- 自动创建出来的基本包装对象的只存在于执行代码的那一行,即执行结束后离开销毁;
- new操作符创建的引用类型,在执行流离开当前作用域之前一直被保存在内存中。
2. 如何理解BigInt
-
什么是BigInt?
-当整数值大于Number数据类型支持的范围时。这种数据类型允许我们安全的对大整数进行算术操作。
-
为什么需要BigInt?
- 在JS中,所有数字都以精度64位浮点格式表示非常;
-
如何创建并使用BigInt?
-
- 在数字末尾加n;
console.log(999999999997867667657578n);
- 在数字末尾加n;
-
- 用BigInt()构造函数;
BigInt('8789658787767565678765'); //8789658787767565678765n
- 用BigInt()构造函数;
-
-
注:
+10n; //TyperError: Cannot convert a BigInt value to a number;
- 不支持一元加号运算符;
- 不允许BigInt和Number之间进行混合操作,因为隐式类型转换可能丢失信息;
- 不能将BigInt传递给Web api和内置的JS函数;(这些函数需要Number类型的数字);
-
if(0n){//判断条件为:false ..... }; if(3n){//判断条件为:true .... } - 元素都为BigInt的数组可以sort;
- 可以正常运算;
3.手写instanceof
4. Object.is 和 === 有什么区别?
5. 如何让if(a == 1 && a == 2)条件成立
5.1对象转原始类型的流程
- 如果Symbol.toPrimitive()方法,优先调用;
- 调用valueOf()【效果相当于返回原数据】,转化为原始类型,则返回。
- 调用toString()【效果相当于数据类型转换,将原类型转化为字符串】,转化类型为原始类型,则返回。
- valueOf()、toString()都是Object原型链上的方法,被每个对象继承;
- 对象的Symbol.toPrimitive属性。指向一个方法。该对象被转化为原始类型的值时,会调用这个办法,返回该对象对应的原始类型值;
- Symbol.toPrimitive()的优先级最高;
5.2 应用(答)
6. 闭包
- 闭包:有权访问另一个函数作用域的函数;(高程P178)
- 闭包产生的原因:
- 作用域链:ES5中存在两种作用域:全局作用域和函数作用域;当访问一个变量时,解释器会在当前作用域中查找标识符,若没有,则向上查找(父级->祖父级->……);值得注意的是:每个子作用域都会拷贝上级的作用域,形成作用域链条。
- 闭包的本质:在当前环境存在指向父级作用域的引用,即让父级作用域的引用存在。
- 返回一个函数;
- 作为函数的参数传递;
- 在定时器、事件监听、Ajax请求、跨窗口通信、Web Workers或者任何异步中,只要使用了回调函数,实际上就在使用闭包;
- IIFE(立即执行函数表达式)创建闭包,保存了当前函数作用域和全局作用域window,因此可以访问全局作用域;
- 解决以下问题:
- 补充:JS单线程eventLoop机制,当主线程中的同步任务执行结束后,才会执行异步任务(宏任务--setTimeout,微任务--Promise)
- 方法一:(IIFE--当每次for循环时,把此时的变量i传递到定时器中)
- 方法二:(给定时器传第三个参数,作为timer函数的第一个函数参数)
- 方法三:(使用let声明变量,变为块级作用域)
7. 原型链
- 原型对象和构造函数的关系
- 每当定义一个函数数据类型(普通函数、类)时候,都会天生自带一个prototype属性,这个属性指向函数的原型对象;
- 当函数经过new调用时,这个函数就成为了构造函数,返回一个全新的实例对象,这个实例对象有一个 proto 属性,指向构造函数的原型对象;
- 描述原型链
- JS对象通过prototype指向父类对象,直到指向Object对象为止,这像就形成了一个原型指向的链条,即原型链。
8. 实现继承
- call实现(改变this的指向,并执行函数)
- 原理:将函数作为对象的属性,由对象进行调用。(apply同理,只需要改变参数即可)
- 弊端:一旦父类原型对象中存在方法,那么子类无法继承;
- 借助原型链
- 寄生组合继承(最优)