开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 8 天,点击查看活动详情
在 Vue 中 .once 是事件的修饰符之一,表示事件只会触发一次
<button @click.once="fn" >确定</button>
那么如果要使用 js 来实现和 .once 相同效果,核心思路其实是使用闭包
执行多次,事件只会触发一次
实现思路:
- 设定一个标记,初始为 false,当触发事件,标记值如果为 false,将其值设为 true,执行对应事件;标记值如果为 true,不执行。
- 函数的执行,使用 apply() 来实现
如下代码就应用了高级函数的写法(高阶函数,是指以函数作为参数或以函数作为返回值的函数):
var once = fn => {
let done = false
return function () {
if(!done) {
done = true
fn.apply(this, arguments)
}
}
}
var doSomething = once(() => {
console.log('hello')
})
doSomething()
doSomething()
doSomething()
doSomething()
doSomething()
doSomething()
闭包中的核心代码,也可以简写成:
return done ? undefined : (( done = true), fn.apply(this, arguments))
执行这段代码,运行后可以看到多次执行函数, hello 只输出了一次,效果如下:
关于 apply()
在 js 中,apply、call、bind 都可以用来改变 this 的指向。它可以劫持另外一个对象的方法,继承另外一个对象的属性。
call 和 apply 的区别只有参数的形式不同
- fn.call(this, arg1, arg2);
- fn.apply(this, [arg1, arg2]); // 或 fn.apply(this, arguments)
使用场景的选择:
- 函数参数确定的时候,使用 call
- 如果函数的参数不固定,使用 apply (fn.apply(this, arguments) 是参数不固定的写法,arguments 是一个数组,可遍历所有的参数)
除此之外,如果 call 或 apply 方法的第一参数是 null, this 指向的是 window
apply / call 与 bind 的区别:
- apply / call 会立即执行函数
- bind 不会立即执行函数
如果改变上下文环境之后不需要立即执行,而是回调执行的时候,使用 bind() 方法。同时,使用 bind() 也可以实现立即执行:
fn.call(obj)
// 等价于
fn.bind(obj)()
其它
函数调用的三种方式,写法如下:
- obj.myFunc();
- myFunc.call(obj,arg);
- myFunc.apply(obj,[arg1,arg2..]);