前端面试题-js-new关键字-this指向-js事件流-防抖节流
- new 关键字都做了什么 this指向问题
- JS事件流
- 防抖节流函数
new 关键字都做了什么 this指向问题
1.创建一个简单的空对象
2.原型的绑定,确定对象O的原型链
3.绑定this对象为O,传入参数;执行Person构造函数,进行属性和方法的赋值操作
4.返回结果
普通函数的this指向
函数的this指向有一个基本的原则,谁调用的函数,函数的this就指向谁,否则指向全局
箭头函数的this指向
箭头函数本身没有this,箭头函数的this是定义箭头函数时父级作用域的this,也就是说使用箭头函数的时候,箭头函数内部的this,我们只需要看档箭头函数定义时,该箭头函数的父级的this即可
构造函数指向new出来的新对象
JS事件流
DOM事件流是有两种的,一种是捕获事件一种是冒泡事件
事件捕获(event capturing):由微软公司提出,事件从文档根节点(Document对象)流向目标节点,途中会经过目标节点的各个父级节点,并在这些节点上触发捕获事件,直至到达文档根节点。(下图点击的粉色方块)
事件冒泡(event bubbling):由网景公司提出,与捕获时间相反,世界会从目标节点流向文档的根元素节点,途中会经过目标节点的各个父级节点,并在这些节点上触发捕获事件,直至到达文档的根节点。整个过程就像水中的奇葩一样,从水底向上运动。(下图点击的浅粉色方块)
W3C为了统一标准,采用了折中的方式,即将事件捕获与事件冒泡合并,也就是现在的先捕获后冒泡。
怎么阻止事件冒泡
1.w3c: event.stopPropagation()
2.IE: window.event.cancelBubble = true
3.vue (扩展)事件修饰符stop
** 怎么阻止默认事件**
event.preventDefault()
什么是事件委托
使用事件冒泡原理,自己所触发的事件,让其父元素代为执行
例如:富文本解析在不改变富文本内容的情况下给图片实现点击放大预览效果 可以把事件给到解析富文本的那个盒子 然后通过event 去判断点击是不是图片 再进行下面的事件处理
防抖节流函数
函数防抖:规定涣散至少间隔多久执行(窗口大小的变化,模糊查询)
函数节流 :规定函数在某时间段内最多执行一次(典型案例就是鼠标不断点击触发,规定在n秒内多次点击只有一次生效,用户登录等场景)
函数防抖和函数节流的对比:
不管是函数节流还是函数防抖,减少都是事件处理程序的调用频率,而不是时间的调用频率。
何时使用函数防抖,何时使用函数节流
当我们只需要处理最后一次触发的事件时,用函数防抖。
当事件触发过于频繁,我们需要限制事件处理程序的调用频率,用函数节流
用vue写函数防抖节流指令
export default {
install(Vue, Options) {
/*
* 防抖,规定时间内(默认300毫秒)最后一次点击有效。
* @param {?Number|300} time - 间隔时间,毫秒
* @param {Function} fn - 执行函数
* @param {?String|"click"} event - 事件类型 例:"click"
* @param {Array} binding.value - [fn,event,time]
* 例:<el-button v-debounce="[resetData,`click`,300]">刷新</el-button>
* 也可简写成:<el-button v-debounce="[resetData]">刷新</el-button>
*/
// 注册一个全局自定义指令 `v-debounce`
Vue.directive('debounce', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el, binding) {
//binding.value,使用自定义指令v-debounce时填写的参数
//解构赋值,定义了3个变量,将参数(数组)按顺序进行赋值
let [fn, event = "click", time = 300] = binding.value
let timer
el.addEventListener(event, () => {
//默认监听的事件为click
//判断计时器是否存在,存在则清除计时器。重新创建计时器,到时间后执行函数fn
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => fn(), time)
})
}
})
/*
* 节流,规定时间内可点击一次(第一次点击有效)。
* @param {?Number|300} time - 间隔时间,毫秒
* @param {Function} fn - 执行函数
* @param {?String|"click"} event - 事件类型 例:"click"
* @param {Array} binding.value - [fn,event,time]
* 例:<el-button v-throttle="[resetData,`click`,300]">刷新</el-button>
* 传递参数则:<el-button v-throttle="[()=>resetData(param),`click`,300]">刷新</el-button>
*/
// 注册一个全局自定义指令 `v-throttle`
Vue.directive('throttle', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el, binding) {
//binding.value,使用自定义指令v-throttle时填写的参数
//解构赋值,定义了3个变量,将参数(数组)按顺序进行赋值
let [fn, event = "click", time = 300] = binding.value
let timer = null;
el.addEventListener(event, () => {
//默认监听的事件为click
//判断计时器是否存在,不存在则执行函数fn,创建计时器
if (timer == null) {
fn();
timer = setTimeout(() => timer = null, time)
}
})
}
})
/*
* 节流方案二,通过禁用html标签,规定时间内可点击一次(第一次点击有效)。
* 应用在封装的组件中可能无效。
* @param {?String|"click"} event - 事件类型 例:"click"
* @param {?Number|2000} time - 间隔时间,毫秒
* @param {Array} binding.value - [event,time]
* 例:<button v-throttle-disabled="[]">测试按钮</button>
*/
//注册一个全局自定义指令 `v-throttle-disabled`
Vue.directive('throttle-disabled', {
// 当被绑定的元素插入到 DOM 中时……
inserted(el, binding) {
let [event = "click", time = 2 * 1000] = binding.value
el.addEventListener(event, () => {
//默认监听click事件
//当 dom元素el 非禁用状态时 将其设置为禁用状态,同时设置计时器,规定时间后(默认2秒)启用。
if (!el.disabled) {
el.disabled = true
setTimeout(() => {
el.disabled = false
}, time)
}
})
}
})
}
}