面试题总结
1)深拷贝和浅拷贝的区别
浅拷贝会创建一个新的对象,但对象中的引用类型数据仍然是原始对象中的引用,因此修改新对象中的引用类型数据会影响原始对象;
深拷贝会创建一个全新的对象,并且递归地将原始对象的所有属性及其引用类型数据都复制到新对象中,因此修改新对象中的引用类型数据不会影响原始对象。
2)什么是递归函数
如果一个函数在内部调用自身本身,这个函数就是递归函数
3)js的this指向问题
this是Javascript语言的一个关键字
有一个总的原则,那就是this指的是调用函数的那个对象.
在全局范围内使用this ,它将指向全局对象(浏览器中为 window)
字面量对象中的this:指的就是对象本身
箭头函数中的this:谁定义了箭头函数,this就是谁
4)call,apply,bind的区别
所有函数都是对象,都有call(),apply(),bind()方法,都是为了改变this指向
- call 和 apply 特性一样
都是用来调用函数,而且是立即调用
但是可以在调用函数的同时,通过第一个参数指定函数内部 this 的指向
call 调用的时候,参数必须以参数列表的形式进行传递,也就是以逗号分隔的方式依次传递即可
apply 调用的时候,参数必须是一个数组,然后在执行的时候,会将数组内部的元素一个一个拿出来,与形参一一对应进行传递
如果第一个参数指定了 null 或者 undefined 则内部 this 指向 window
- bind
可以用来指定内部 this 的指向,然后生成一个改变了 this 指向的新的函数
它和 call、apply 最大的区别是:bind 不会调用
纯函数指的是什么
纯函数是指在编程中的一种特殊函数,它具有以下两个主要特点:
输入和输出关联:纯函数的输出结果只依赖于输入参数,对于相同的输入,总是得到相同的输出。不会受到外部状态或其他随机因素的影响。
无副作用:纯函数不会对除了返回值之外的任何数据产生影响,包括修改输入参数或全局变量、产生可观察的状态变化、进行网络调用等。
什么是科里化,科里化主要用到的是什么特性?
科里化(Currying)是一种将接受多个参数的函数转化为接受一个参数,并返回一个接受剩余参数的新函数的过程。
在科里化中,一个函数接收多个参数时,我们可以将其转化为一系列接受单个参数的函数调用链。每次调用只提供一个参数,返回一个新的函数,直到所有参数都被传递完毕,最后返回函数的执行结果。
科里化的主要特性包括:
参数复用:通过科里化,我们可以部分应用函数的参数,生成一个新的函数,该函数可以重复使用并接受其他参数来完成计算。
延迟执行:科里化允许我们在接收部分参数时延迟函数的执行。当所有参数齐全后,再执行函数并返回结果。
函数的高阶特性:通过科里化,我们可以更好地支持函数的柯里化组合和复杂的函数组合,使代码更加模块化和可组合。
科里化有助于提高代码的可读性、复用性和灵活性。它常常与函数式编程一起使用,并广泛应用于JavaScript和其他函数式编程语言中。函数库如Lodash和Ramda等也提供了科里化的辅助函数来方便开发者进行函数组合和高级函数操作。
javaScript中有哪些常见的编程模式?
命令式编程模式(Imperative Programming):以一系列命令的方式描述程序的执行过程,通过指定详细的指令来实现程序的控制流程和逻辑。
函数式编程模式(Functional Programming):将计算过程看作是函数的组合和变换,强调函数的纯粹性和不可变性,避免使用共享状态和可变数据,更加关注输入和输出之间的映射关系。
面向对象编程模式(Object-Oriented Programming,OOP):以对象作为编程的基本单位,通过封装、继承和多态等概念,模拟现实世界中的对象关系,强调对象之间的相互作用和信息传递。
原型模式(Prototype Pattern):基于JavaScript的原型继承机制,通过原型链的方式实现对象的创建和继承,允许对象实例共享属性和方法。
模块化模式(Module Pattern):通过将功能和状态封装在独立的模块中,实现代码的分割和组织,避免全局变量的冲突和污染,提高代码的可维护性和复用性。
观察者模式(Observer Pattern):定义对象之间一种一对多的关系,当一个对象的状态发生变化时,它的所有依赖者都会收到通知并自动更新。
发布订阅模式(Publish-Subscribe Pattern):类似于观察者模式,将观察者与被观察者解耦,通过事件的发布和订阅来实现组件间的消息传递。
单例模式(Singleton Pattern):确保一个类只有一个实例,并提供全局访问的方式。
javaScript中有个概念叫做副作用,副作用指的是什么?
常见的副作用包括但不限于以下情况:
修改全局变量或外部状态。
修改函数参数。
修改对象属性。
抛出异常。
发起网络请求。
读写文件或数据库。
打印日志或输出到控制台。
什么是数据劫持,数据劫持有什么作用?如何实现数据劫持?
数据劫持的主要作用包括:
监听属性变化:可以通过数据劫持来监听对象属性的变化,一旦属性发生改变,就可以触发相应的回调函数执行其他逻辑。
数据验证:可以在属性被修改之前进行数据验证,确保属性值满足特定的条件和规则。
计算属性:可以基于对象的属性计算衍生出新的属性,使得对象的行为更加丰富和灵活。
数据绑定:可以实现对象属性间的绑定关系,当一个属性变化时,自动更新相关的绑定属性。
什么是原型什么是原型链?
1. 如果再构造函数中有方法,我们需要把方法放入到原型中。
好处:共用一个内存地址
原型对象:所有的构造函数再初始化的时候,都会自动创建出一个特殊的实例化对象,构造函数的prototype属性 指向的就是该对象,该对象被称为是原型对象,或者prototype对象
2. prototype属性:所有的构造函数new出来的实例化对象,都会有一个prototype属性,这个prototype属性指向的构造函数的原型对象(110内存地址)
调用属性和方法的时候,先去构造中查找,如果构造中没有,会沿着prototype属性的内存地址,再原型对象中查找有没有对应的方法
3. 原型对象是为了实现继承
4. 原型链:由prototype属性,串联起来的原型对象,就称为是原型链
5. 原型链的意义:实例化对象中访问属性和方法的时候,先访问自身的属性和方法,本身不存在,则会通过prototype属性,再整个原型链上查找,如果整个都查找不到就会报错
new的4个阶段
1. 创建一个空的实例化对象
2. 把构造函数中的this指向创建出来的实例化对象中
3. 调用构造函数,实例化对象,就有了属性和方法
4. 返回一个实例化对象