1、对作用域的理解
答: (1)、概念:在JS中,作用域是指在程序中定义变量的可见范围
(2)、分类:全局作用域和函数作用域
全局作用域:指在代码任何地方都可以访问的变量,它们在整个应用程序中都可见
函数作用域:指在函数内部定义的变量,它们只能在函数内部访问,外部无法访问
(3)、JS中还有一个特殊的作用域,即块级作用域。在ES6之前,JS中没有块级作用域。ES6中,使用let和const关键字可以常见块级作用域。块级作用域是指代码块中定义的变量,它们只能在该代码块内部访问,代码块外部无法访问
2、new操作符原理
答:(1)、首先创建一个新的空对象
(2)、设置原型,将对象的原型设置为函数的prototype
(3)、让函数的this指向这个对象,执行构造函数的代码
(4)、判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象
3、instanceof原理
答:instanceof运算符用于判断构造函数的prototype属性是否出现在对象的原型链中的任何位置
4、值类型和引用类型的区别
答:(1)、值类型存在在栈中,存放的时内容;引用类型的在栈中存放的时执行内容的地址,内容存放在堆中
(2)、简单类型赋值,是生成相同的值,两个对象对应不同的地址;复杂数据类型,是将保存对象的内存地址赋值给另一个变量。也就是两个变量指向堆内存中同一个对象
5、如何实现深拷贝和浅拷贝?
答:浅拷贝:(1)、直接赋值
(2)、Object.assign()
(3)、扩展运算符
(4)、数组方法实现数组浅拷贝
深拷贝: (1)、loadsh中的_.cloneDeep()方法
(2)、JSON.stringify() JSON.parse()
(3)、递归
6、什么是原型和原型链?
答: (1)、概念:原型链是JavaScript中实现继承的一种机制。每个实例对象(object)都有一个私有属性(称之为 __proto__ )指向它的构造函数的原型对象(prototype)。该原型对象也有一个自己的原型对象(__proto__),层层向上直到一个对象的原型对象为 null 。这样就形成了一个原型链。
(2)、例子:如果在当前对象中查找某个属性或方法时,当前对象不存在该属性或方法,JavaScript 引擎会沿着原型链向上查找,直到找到该属性或方法为止,或者查找到原型链的顶端。
(3)、缺点:在原型链上查找属性比较耗时,对性能有副作用,这在性能要求苛刻(一般情况基本无影响)的情况下很重要。另外,试图访问不存在的属性时会遍历整个原型链(这点也很重要,需要记住)。
7、call、apply、bind的区别
答: (1)、call和apply方法都可以调用函数,方法内的第一个参数可以修改this的指向
(2)、call方法可以有多个参数,除了第一个参数,其他参数作为实参传递给函数,apply方法最多有2个参数,第二个参数是个数组或伪数组,数组里面的每一项作为实参传递给函数
(3)、bind方法不能调用函数,它会创建一个副本函数,并且绑定新函数的this指向bind返回的新的函数
8、数组扁平化
答: (1)、利用Array.some方法判断数组中是否存在数组,es6展开运算符连接数组
(2)、使用数组的concat方法
(3)、使用数组的concat方法和扩展运算符
(4)、es6中的flat函数也可以实现数组的扁平化
9、对闭包的理解
答:(1)、概念:闭包是指有权访问另一个函数作用域中变量的函数,优点是私有化数据,在私有化数据的基础上保持数据,缺点使用不恰当会导致内存泄漏,在不需要用到的时候及时把变量置为null
(2)、场景:防抖、节流、柯里化等
10、为数组和真数组的区别
答: (1)、伪数组不具备真数组的方法 比如:push、pop、splice等
(2)、它们的数据类型不同 真数组是Array,伪数组是Object
(3)、真数组的长度是可变的,伪数组不可以
(4)、伪数组没有_proto_和prototype
11、let、const、var的区别
答: (1)、var声明变量存在提升,let和const存在块级作用域
(2)、var没有块级作用域,let和const存在块级作用域
(3)、var允许重复声明,let和const在同一作用域不允许重复声明
(4)、var和let声明变量可以修改,const是常量不能改变