- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
apply、call和bind都是系统提供给我们的内置方法,每个函数都可以使用这三种方法,是因为apply、call和bind都实现在了Function的原型上(Function.prototype),而他们的作用都是给我们函数调用时显式绑定上this。下面先介绍一下它们的基本用法:
apply方法:调用一个具有给定this值的函数,以及以一个**数组(或类数组对象)**的形式提供的参数。
使用语法:func.apply(thisArg, [argsArray])
thisArg:在func函数调用时绑定的this值;
[argsArray]:一个数组或者类数组对象,其中的数组元素将作为单独的参数传给func函数;
使用效果:
function foo(x, y ,z) {
console.log(this, x, y, z)
}
const obj = { name: 'curry', age: 30 }
/**
* 1.将obj对象绑定给foo函数的this
* 2.数组中的1 2 3分别传递给foo函数对应的三个参数
*/
foo.apply(obj, [1, 2, 3])
call方法:使用一个指定的 this值和单独给出的一个或多个参数来调用一个函数。
使用语法:func.call(thisArg, arg1, arg2, ...)
thisArg:在func函数调用时绑定的this值;
arg1, arg2, ...:指定的参数列表,将作为参数传递给func函数;
使用效果:
function foo(x, y ,z) {
console.log(this, x, y, z)
}
const obj = { name: 'curry', age: 30 }
/**
* 1.将obj对象绑定给foo函数的this
* 2.call剩余参数中的a b c分别传递给foo函数对应的三个参数
*/
foo.call(obj, 'a', 'b', 'c')
bind方法:创建一个新的函数,在bind()被调用时,这个新函数的this被指定为bind()的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
使用语法:func.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg:调用func函数时作为this参数传递给目标函数的值;
arg1, arg2, ...:当目标函数被调用时,被预置入func函数的参数列表中的参数;
使用效果:
function foo(...args) {
console.log(this, ...args)
}
const obj = { name: 'curry', age: 30 }
/**
* 1.将obj对象绑定给foo函数的this
* 2.bind剩余参数中的1 2 3分别传递给foo函数中参数
* 3.也可在newFoo调用时传入参数,这时bind传递的参数会与newFoo调用时传递的参数进行合并
*/
const newFoo = foo.bind(obj, 1, 2, 3)
newFoo()
newFoo('a', 'b', 'c')
总结:
为了所有定义的函数能够使用我们自定义的apply、call和bind方法,所以需要将自己实现的方法挂在Function的原型上,这样所有的函数就可以通过原型链找到自定义的这三个方法了。
Function.prototype.myApply = function(thisArg, argArray) {
// 1.获取当前需要被执行的函数
// 因为myApply是需要被当前函数进行调用的,根据this的隐式绑定,此处的this就是指向当前需要被执行的函数
const fn = this
// 2.对传入的thisArg进行边界判断
if (thisArg === null || thisArg === undefined) {
// 当传入的是null或者undefined是,被执行函数的this直接指向全局window
thisArg = window
} else {
// 将传入的thisArg对象化,方便后面在thisArg添加属性
thisArg = Object(thisArg)
}
// 也可简单写成三元运算符:
// thisArg = (thisArg === null || thisArg === undefined) ? window : Object(thisArg)
// 3.将获取的fn添加到thisArg对象上
// 这里使用Symbol的原因是避免外部传入的thisArg中的属性与添加fn有冲突
const fnSymbol = Symbol()
Object.defineProperty(thisArg, fnSymbol, {
enumerable: false,
configurable: true,
writable: false,
value: fn
})
// 也可简单写成
// thisArg[fnSymbol] = fn
// 4.对argArray进行判断
// 看是否有传入值,没有值传入就默认 []
argArray = argArray || []
// 5.调用获取的fn函数,并将对应传入的数组展开传递过去
const result = thisArg[fnSymbol](...argArray)
// 调用完后删除添加的属性
delete thisArg[fnSymbol]
// 6.将结果返回
return result
}
测试:虽然打印出来的对象中还存在Symbol属性,实际上已经通过delete
删除了,这里是对象引用的问题。
function foo(x, y, z) {
console.log(this, x, y, z)
}
foo.myApply({name: 'curry'}, [1, 2, 3])
call方法的实现和apply方法的实现差不多,主要在于后面参数的处理。
Function.prototype.myCall = function(thisArg, ...args) {
// 1.获取当前需要被执行的函数
const fn = this
// 2.对传入的thisArg进行边界判断
thisArg = (thisArg === null || thisArg === undefined) ? window : Object(thisArg)
// 3.将获取的fn添加到thisArg对象上
const fnSymbol = Symbol()
thisArg[fnSymbol] = fn
// 4.调用获取的fn函数,并将对应传入的args传递过去
const result = thisArg[fnSymbol](...args)
// 调用完后删除添加的属性
delete thisArg[fnSymbol]
// 5.将结果返回
return result
}
测试:
function foo(x, y, z) {
console.log(this, x, y, z)
}
foo.myCall({name: 'curry'}, 1, 2, 3)
bind方法的实现稍微复杂一点,需要考虑到参数合并的问题。
Function.prototype.myBind = function(thisArg, ...argsArray) {
// 1.获取当前的目标函数,也就是当前使用myBind方法的函数
const fn = this
// 2.对传入的thisArg进行边界判断
thisArg = (thisArg === null || thisArg === undefined) ? window : Object(thisArg)
// 3.将获取的fn添加到thisArg对象上
const fnSymbol = Symbol()
thisArg[fnSymbol] = fn
// 4.定义一个新的函数
function newFn(...args) {
// 4.1.合并myBind和newFn传入的参数
const allArgs = [...argsArray, ...args]
// 4.2.调用真正需要被调用的函数,并将合并后的参数传递过去
const result = thisArg[fnSymbol](...allArgs)
// 4.3.调用完后删除添加的属性
delete thisArg[fnSymbol]
// 4.4.将结果返回
return result
}
// 6.将新函数返回
return newFn
}
测试:
function foo(x, y, z) {
console.log(this, x, y, z)
}
const newFoo = foo.myBind({ name: 'curry' }, 1, 2)
newFoo(3)
我不知道该怎么做... function f1() { var x = 10; function f2(fx) { var x; x = 6;
早期绑定(bind)和后期绑定(bind)有什么区别? 最佳答案 简短的回答是,早期(或静态)绑定(bind)是指编译时绑定(bind),后期(或动态)绑定(bind)是指运行时绑定(bind)(例如
如何在 SwiftUI View 上使用 Binding(get: { }, set: { }) 自定义绑定(bind)与 @Binding 属性。我已成功使用此自定义绑定(bind)与 @State
我经常发现自己遇到问题,即控件的两个(相关)值被更新,并且两者都会触发昂贵的操作,或者控件可能会暂时处于不一致的状态。 例如,考虑一个数据绑定(bind),其中两个值 (x,y) 相互减去,最终结果用
我想通过我的 ViewModel 控制我的一个窗口的高度和宽度。 这看起来很简单。 但没有。它不起作用。 它检查 ViewModel 的 Width但不是 Height . 奇怪的是,如果我切换 W
UI5中一次性绑定(bind)和单向绑定(bind)有什么区别? 是否有任何用户特定的用例我会使用它们? 我无法从文档中获得太多信息。 最佳答案 单程 它的作用:单向数据流。模型数据的变化(例如通过
(define make (lambda (x) (lambda (y) (cons x (list y))))) (let ((x 7) (p (make 4))) (cons
尽管我或多或少地了解什么是语言绑定(bind),但我很难理解它们是如何工作的。 例如,谁能解释一下如何为 WinAPI 制作 Java 绑定(bind)? 最佳答案 如果您搜索 Foreign Fun
谁能解释为什么我可以重新绑定(bind)列表但不能+? (binding [list vector] (list 1 3)) (binding [list +] (list 1 3)) (bi
我真的很喜欢 Caliburn 和命名约定绑定(bind),我很惊讶 可见性与“CanNAME”约定用于保护 Action 的方式不同。 据我所知, BooleanToVisibilityConver
我了解动态绑定(bind)的实现方式以及静态绑定(bind)和动态绑定(bind)之间的区别,但我只是无法理解动态绑定(bind)的定义。基本上它是一种运行时绑定(bind)类型。 最佳答案 基本上,
http://jsfiddle.net/3NRsd/ var foo = $("div").bind("click", function() { $("div").animate({"hei
这个问题我快疯了...我有一个用户控件,它有一个用于插入操作的 FormView 和一个用于所有其他操作的 GridView。 在这两个控件中,我都有一个 DropDownList,如下所示: '
我有一个绑定(bind)到 ListBox 的地址的 ObservableCollection。然后在 ItemTemplate 中,我使用 {Binding .} 绑定(bind)到当前地址记录。这
如果我有以下简单的 js/knockout 代码: .js( View 模型): var image = ko.observable('http://placehold.it/300x150'); 看
我正在 aurelia 上开发一个自定义属性,让用户在输入文本区域时从列表中进行选择。例如,用法将是这样的: 正如您可能注意到的,auto-complete是属性。现在,当我想显示提示时,我想在自定
我正在使用 EventEmitter2作为我的应用程序内部的消息总线。现在我需要绑定(bind)和取消绑定(bind)一些事件处理程序。因为我也希望他们bind将它们添加到给定的上下文中,我最终得到以
我有以下函数调用: $(".selector").on("click", callback.bind(this, param1, param2)); 在我的回调函数中,我想使用绑定(bind)的 th
我目前正在试验新的编译绑定(bind),并且(再次)达到了我在拼图中遗漏了一个小问题:为什么我必须调用 Bindings.Update?直到现在,我还认为实现 INotifyPropertyChang
我正在阅读一本关于编写 JavaScript 框架的书,并找到了这段代码。但是我不明白它是如何工作的,尤其是 bind.bind 的用法?有人知道吗? var bind = Function.prot
我是一名优秀的程序员,十分优秀!