You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
functionPerson(name,age){this.name=name;this.age=age;this.say=function(){console.log(this.name+":"+this.age);}}functionStudent(name,age,job){Person.call(this,name,age);this.job=job;this.say=function(){console.log(this.name+":"+this.age+" "+this.job);}}varme=newStudent("axuebin",25,"FE");console.log(me.say());// axuebin:25 FE
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
整理
call
、apply
、bind
这三个方法的的知识点。之前这篇文章提到过
this
的各种情况,其中有一种情况就是通过call
、apply
、bind
来将this
绑定到指定的对象上。也就是说,这三个方法可以改变函数体内部
this
的指向。这三个方法有什么区别呢?分别适合应用在哪些场景中呢?
先举个简单的栗子 ~
对于对象
person
而言,并没有say
这样一个方法,通过call
/apply
/bind
就可以将外部的say
方法用于这个对象中,其实就是将say
内部的this
指向person
这个对象。call
call
是属于所有Function
的方法,也就是Function.prototype.call
。它的语法是这样的:
其中,
thisArg
就是this
指向,arg
是指定的参数。call
的用处简而言之就是可以让call()中的对象调用当前对象所拥有的function。ECMAScript规范
ECMAScript规范中是这样定义
call
的:当以
thisArg
和可选的arg1
,arg2
等等作为参数在一个func
对象上调用call
方法,采用如下步骤:IsCallable(func)
是false
, 则抛出一个TypeError
异常。argList
为一个空列表。arg1
开始以从左到右的顺序将每个参数插入为argList
的最后一个元素。thisArg
作为this
值并以argList
作为参数列表,调用func
的[[Call]]
内部方法,返回结果。call
方法的length
属性是1。在外面传入的
thisArg
值会修改并成为this
值。thisArg
是undefined
或null
时它会被替换成全局对象,所有其他值会被应用ToObject
并将结果作为this
值,这是第三版引入的更改。使用call调用函数并且指定this
call实现继承
在需要实现继承的子类构造函数中,可以通过
call
调用父类构造函数实现继承。apply
apply
也是属于所有Function
的方法,也就是Function.prototype.apply
。它的语法是这样的:
其中,
thisArg
就是this
指向,argsArray
是指定的参数数组。通过语法就可以看出
call
和apply
的在参数上的一个区别:call
的参数是一个列表,将每个参数一个个列出来apply
的参数是一个数组,将每个参数放到一个数组中ECMAScript规范
当以
thisArg
和argArray
为参数在一个func
对象上调用apply
方法,采用如下步骤:IsCallable(func)
是false
, 则抛出一个TypeError
异常 .argArray
是null
或undefined
, 则thisArg
作为this
值并以空参数列表调用func
的[[Call]]
内部方法的结果。Type(argArray)
不是Object
, 则抛出一个TypeError
异常 .len
为以"length"
作为参数调用argArray
的[[Get]]
内部方法的结果。n
为ToUint32(len)
.argList
为一个空列表 .index
为0.index
<n
就重复indexName
为ToString(index)
.nextArg
为以indexName
作为参数调用argArray
的[[Get]]
内部方法的结果。nextArg
作为最后一个元素插入到argList
里。index
为index + 1
.thisArg
作为this
值并以argList
作为参数列表,调用func
的[[Call]]
内部方法,返回结果。apply
方法的length
属性是 2。在外面传入的
thisArg
值会修改并成为this
值。thisArg
是undefined
或null
时它会被替换成全局对象,所有其他值会被应用ToObject
并将结果作为this
值,这是第三版引入的更改。用法
在用法上
apply
和call
一样,就不说了。实现一个apply
参考链接:jawil/blog#16
第一步,绑定上下文
确实成功地将
this
指向了me
对象,而不是本身的obj
对象。第二步,给定参数
上文已经提到
apply
需要接受一个参数数组,可以是一个类数组对象,还记得获取函数参数可以用arguments
吗?context.fn(...arg)
是用了ES6的方法来将参数展开,如果看过上面那个链接,就知道这里不通过...
运算符也是可以的。原博主通过拼接字符串,然后用
eval
执行的方式将参数传进context.fn
中:第三步,当传入apply的this为null或者为空时
我们知道,当
apply
的第一个参数,也就是this
的指向为null
时,this
会指向window
。知道了这个,就简单了~第四步 保证fn函数的唯一性
ES6中新增了一种基础数据类型
Symbol
。所以我们可以通过
Symbol
来创建一个属性名。完整的apply
这样就是一个完整的
apply
了,我们来测试一下:ok 没啥毛病 ~
再次感谢1024大佬 ~
bind
语法:
其中,
thisArg
就是this
指向,arg
是指定的参数。可以看出,
bind
会创建一个新函数(称之为绑定函数),原函数的一个拷贝,也就是说不会像call
和apply
那样立即执行。当这个绑定函数被调用时,它的
this
值传递给bind
的一个参数,执行的参数是传入bind
的其它参数和执行绑定函数时传入的参数。用法
当我们执行下面的代码时,我们希望可以正确地输出
name
,然后现实是残酷的这里
this
运行时是指向window
的,所以this.name
是undefined
,为什么会这样呢?看看MDN的解释:有一个常见的方法可以使得正确的输出:
没错,这里我们就可以用到
bind
了:MDN的Polyfill
总结
this
指向this
指向的对象bind
是返回一个绑定函数可稍后执行,call
、apply
是立即调用call
给定参数需要将参数全部列出,apply
给定参数数组感谢
不用call和apply方法模拟实现ES5的bind方法
深入浅出妙用 Javascript 中 apply、call、bind
回味JS基础:call apply 与 bind
The text was updated successfully, but these errors were encountered: