1,什么是函数防抖和函数节流?有什么区别
防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会清除前一次重新开启计算函数执行时间
相比于防抖,节流就是在让函数在特定的时间内只执行一次
函数节流与函数防抖是我们解决频繁触发DOM事件的两种常用解决方案
函数防抖 debounce
原理:将若干函数调用合成为一次,并在给定时间过去之后,或者连续事件完全触发完成之后,调用一次
例如:滚动scroll事件,不停滑动滚轮会连续触发多次滚动事件,从而调用绑定的回调函数,我们希望当我们停止滚动的时,才触发一次回调,这时可以使用函数防抖。
函数节流 throttle
原理:当达到了一定的时间间隔就会执行一次;可以理解为是缩减执行频率
例如:还是以scroll滚动事件来说吧,滚动事件是及其消耗浏览器性能的,不停触发。以我在项目中碰到的问题,移动端通过scroll实现分页,不断滚动,我们不希望不断发送请求,只有当达到某个条件,比如,距离手机窗口底部150px才发送一个请求,接下来就是展示新页面的请求,不停滚动,如此反复;这个时候就得用到函数节流。
函数节流与函数防抖的区别:
我们以一个案例来讲一下它们之间的区别:设定一个间隔时间为一秒,在一分钟内,不断的移动鼠标,让它触发一个函数,打印一些内容。
函数防抖:会打印1次,在鼠标停止移动的一秒后打印。
函数节流:会打印60次,因为在一分钟内有60秒,每秒会触发一次。
2,什么是函数柯里化及有什么用?
函数的多参,变成单参或减少
柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。
通过函数柯里化,我们可以实现参数复用、提前返回和延迟执行。通过函数柯里化,在不同的情况下传递不同的参数
3,谈谈模块化开发
模块化就是将一个复杂的系统分解成多个独立的模块的代码组织方式。
什么是模块化开发?
模块就是完成单一的职责的功能函数或者代码块。
模块化开发是指如何开发新的模块和复用已有的模块来实现应用的功能。
为什么要模块化开发?
可维护性
可测试性
按需加载
代码复用
利于架构
利于协作
模块化开发的规范
CommonJS
用于服务端模块化编程,Node.js就采用此规范;
一个文件就是一个模块,require方法用来加载模块,该方法读取一个文件并执行,最后返回文件内部的module.exports对象;
AMD
require.js(前端模块化管理的工具库)实现js文件的异步加载,避免网页失去响应;管理模块之间的依赖性,便于代码的编写和维护;require.js是使用创建script元素,通过指定script元素的src属性来实现加载模块的;
依赖前置,尽早的执行模依赖块,执行顺序不一定;
CMD
Sea.js 依赖就近,且在真正需要使用依赖模块时才执行该模块,顺序固定;
AMD和CMD最大的区别是对依赖模块的执行时机处理不同,而不是加载的时机或者方式不同,二者皆为异步加载模块;
AMD依赖前置,js可以方便知道依赖模块是谁,立即加载;而CMD就近依赖,需要使用把模块变为字符串解析一遍才知道依赖了那些模块。
ES6
ES6使用的是基于文件的模块。所以必须一个文件一个模块,不能将多个模块合并到单个文件中去。
ES6模块API是静态的,一旦导入模块后,无法再在程序运行过程中增添方法。
ES6模块采用引用绑定(可以理解为指针)。这点和CommonJS中的值绑定不同,如果你的模块在运行过程中修改了导出的变量值,就会反映到使用模块的代码中去。所以,不推荐在模块中修改导出值,导出的变量应该是静态的。
ES6模块采用的是单例模式,每次对同一个模块的导入其实都指向同一个实例。
另外,ES6模块好处很多,但是并不支持按需加载的功能, 而按需加载又是Web性能优化中重要的一个环节。好在我们可以借助Webpack来弥补这一缺陷
更多关于模块化开发的知识:浅谈模块化开发
4,谈谈你对作用域链的理解
什么是作用域?
作用域就是变量与函数的可访问范围。在JavaScript中,变量的作用域有全局作用域和局部作用域,在ES6之后,又添加了块级作用域的概念,所以在JavaScript中有三种作用域。
作用域链
对于javascript而言,我们定义在局部作用域或者块级作用的变量,会存放在scope局部作用域对象上,而定义在全局作用域的变量,会存放在window/global这个全局对象上。
当我们在局部/块级作用域中,调用一个外部的变量时,就会产生作用域链。
当我们在一个函数内部访问当前作用域内不存在的变量时,就会逐层向外查找,如果一直没有找到就会报错。
对于函数而言,函数在哪里创建,它就会从哪里开始向上查找变量;而不是函数在哪里调用。
最常见的就是闭包,通过闭包定义的函数来访问函数的内部变量。
5,什么是深拷贝?什么是浅拷贝?如何实现一个深拷贝函数?
深拷贝和浅拷贝都是针对于引用类型(Object)而言,对于基本数据类型而言,赋值直接就是深拷贝。
浅拷贝
浅拷贝有两种定义,一种是直接赋值引用,另一种是只拷贝对象的第一层属性,更深层次的引用还是相同的;对于这两种,哪一种是正确的答案,这里不做多的解释,看个人理解,像我平时更倾向于第二种。
深拷贝
对于浅拷贝有概念之后,就比较容易理解深拷贝了。
深拷贝就是将原有对象重新拷贝一份,不论是修改哪一部分的值,都不会对原有对象造成影响。拷贝的永远是值,而不是引用。