

#yyds干货盘点#聊聊javascript——call、applay、bind
source link: https://blog.51cto.com/u_11365839/5857829
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

#yyds干货盘点#聊聊javascript——call、applay、bind
精选 原创call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
使用方法:
name: 'johnny'
}
function foo() {
console.log(this.name)
}
foo.call(bar); // johnny
首先 call 是个原型方法,所以一个函数能很自然的使用此方法,即 foo 的 call 方法继承自 Function.prototype.call。其次,call 方法中传入的值会成为 foo 函数的 this 未来指向的对象
其本质是改变 this 指向,将 this 指向了(call 的)传入值。
实现 call
我们根据之前的描述来实现 call
if (this === Function.prototype) {
return undefined // 防止 Function.prototype.mycall 直接调用
}
const fn = Symbol()
context[fn] = this;
const result = context[fn](...args)
delete context[fn]
return result
}
我们一步步分析,首先不支持Function.prototype.mycall
直接调用,
这个很好理解,Function.prototype 中本来就没有 this,调用了也XXX
因为要考虑如果 context 传入的是 null 呢
如果是 null 的话,context 就指向 window,这个很好理解,防御性代码。
这是 call 函数的关键所在,我们在前文讲 call 示例时,就说到 call 会改变 this 指向,讲 this 指向传入的 context,所以我们在模式实现 call 时,就可以先将 this 存在 context 上的一个属性上,再执行它,this 的规则是谁调用它,它指向谁。这样 this 就指向了 context
return result
删除 context 属性,释放内存,并返回结果值 result
call 实现就是如此,测试一波
name: 'johnny'
}
function foo() {
console.log(this.name)
}
foo.mycall(bar);
context[fn] = this;
const result = context[fn](...args)
apply
apply() 方法调用一个具有给定 this 值的函数,以及以一个数组(或一个类数组对象的形式)提供的参数。
使用方法:
name: 'johnny'
}
function foo(age, hobby) {
console.log(this.name, age, hobby)
}
foo.apply(bar, [28, 'sleep']); // johnny 28 sleep
// call 使用方法
// foo.call(bar, 28, 'sleep');
apply 和 call 使用上差不太多,只是传参方式不同
foo.apply(obj, [param1, param2,...,paramN]) // 第二参数为类数组
所以实现上 和 call 大差不差。
实现 apply
if (this === Function.prototype) {
return undefined
}
const fn = Symbol()
context[fn] = this
let result;
if (!Array.isArray(args)) {
result = context[fn]()
} else {
result = context[fn](...args)
}
delete context[fn]
return result
}
测试一波 myapply
name: 'johnny'
}
function foo(age, hobby) {
console.log(this.name, age, hobby)
}
foo.myapply(bar, [28, 'sleep']); // johnny 28 sleep
bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
使用方法:
name: 'johnny'
}
function foo(age) {
console.log(this.name, age)
}
// 返回一个函数
let bindBar = foo.bind(bar)
bindBar(28) // johnny 28
与 call、apply 一样,它是函数的原型方法,不过与它们不同的是,它是 ES5 新增的方法,它返回的是一个函数(并且它还支持传参)
看到返回的是一个函数,就说明 bind 方法是一个闭包。
实现 bind
if (this === Function.prototype) {
throw new TypeError('Error')
}
const _this = this
return function F(...args2) {
if (this instanceof F) {
return new _this(...args1, ...args2)
}
return _this.apply(context, args1.concat(args2))
}
}
我们分析如何实现 bind
首先 bind 不能原型方法调用,如果使用就提示报错
其次我们根据 bind 的一个特性,对其的使用分为两种
一个绑定函数也能使用 new 操作符创建对象:这种行为就像把原函数当作构造器。提供的 this 值被忽略,同时调用时的参数被提供给模拟函数
也就是说,我们要判断它是否为构造函数调用,如果是则用 new 调用当前函数;如果不是,则使用 apply 来出现 context
if (this instanceof F) {
// 如果是构造函数,则以 foo(即_this)为构造器调用函数
return new _this(...args1, ...args2)
}
// 如果非构造函数,则用 apply 指向代码
return _this.apply(context, args1.concat(args2))
let bar = {
name: 'johnny'
}
function foo(age, hobby) {
console.log(this.name, age, hobby)
}
// 返回一个函数
let bindBar = foo.mybind(bar, 28)
bindBar('sleep') // johnny 28 sleep
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayName = function() {
console.log('my name is ' + this.name)
}
let emptyObj = {}
var FakerPerson = Person.mybind(emptyObj)
var johnny = new FakerPerson('johnny', 28)
johnny.sayName() // my name is johnny
Recommend
-
4
#yyds干货盘点# 单链表实现栈 原创 wx61dbfa0f42bf6 2022-01-17 11:18:41...
-
9
一、作用域环境 在js作用域环境中访问变量是由内向外的,内部作用域可以获得当前作用域下的变量,和当前作用域外层作用域下的变量 外层作用域无法访问内部函数的变量 不同的函数作用域中不能相互访问彼此间的变量 ...
-
8
Modbus协议详解 ?作者介绍:中国DBA联盟(ACDU)成员。目前从事工业自动化软件开发工作。擅长C#、Java、机器视觉、底层算法等语言。2019年成立柒月软件工作室,2021年注册苏州凯捷智能科技有限公司 ?如果文章对你有帮助,欢迎关注、点赞、...
-
6
#yyds干货盘点#THREE.BoxHelper的使用注意 原创 歆冉 2022-01-17 08:55:11...
-
9
1、Spring Data JPA1.1、pom<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"...
-
8
Windows 下搭建ActiveMQ环境 #yyds干货盘点# 原创 梁云亮 2022-01-17 11:25:27...
-
7
STP故障 1、根桥故障 在稳定的STP拓扑里面,非根桥会定期收到来自根桥的BPDU报文,如果根桥发生了故障,停止发送BPDU报文,下游交换机就无法收到来自根桥的BPDU报文。如果下游交换设备在MaxAge(default=20s)内没有收到BPDU报文,就会导致已经...
-
5
#yyds干货盘点#JavaScript的几种继承方式 原创 尼羲 2022-07-08 09:55:19...
-
5
作为前端开发工程师,JavaScript 是我们的主要开发语言,它本身语法比较简单,并且生态系统也非常完善,在社区的影响力越来越大。在我们使用过程中,经常会遇到各种奇怪的问题,让我们经常摸不着头脑。奇怪的 try..catch
-
3
#yyds干货盘点#聊聊前端架构模式 精选 原创 尼羲 2022-10-11 08:13:13...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK