首页 技术 正文
技术 2022年11月15日
0 收藏 419 点赞 4,653 浏览 2967 个字

apply,call,bind都是js给函数内置的一些api,调用他们可以为函数指定this的执行,同时也可以传参。

call

call 接收多个参数,第一个为函数上下文也就是this,后边参数为函数本身的参数。

let obj = {
name: "一个"
}function allName(firstName, lastName) {
console.log(this)
console.log(`我的全名是“${firstName}${this.name}${lastName}”`)
}
// 很明显此时allName函数是没有name属性的
allName('我是', '前端') //我的全名是“我是前端” this指向window
allName.call(obj, '我是', '前端') //我的全名是“我是一个前端” this指向obj

apply

apply接收两个参数,第一个参数为函数上下文this,第二个参数为函数参数只不过是通过一个数组的形式传入的。

allName.apply(obj, ['我是', '前端'])//我的全名是“我是一个前端” this指向obj

bind

bind 接收多个参数,第一个是bind返回值是一个函数上下文的this,不会立即执行。

        let obj = {
name: "一个"
} function allName(firstName, lastName, flag) {
console.log(this)
console.log(`我的全名是"${firstName}${this.name}${lastName}"我的座右铭是"${flag}"`)
}
allName.bind(obj) //不会执行
let fn = allName.bind(obj)
fn('我是', '前端', '好好学习天天向上') // 也可以这样用,参数可以分开传。bind后的函数参数默认排列在原函数参数后边
fn = allName.bind(obj, "你是")
fn('前端', '好好学习天天向上')

实现call

1.call主要都做了些什么。

  • 更改this指向
  • 函数立刻执行

2.简单实现

Function.prototype.myCall = function(context) {
context.fn = this;
context.fn();
}const obj = {
value: 'hdove'
}function fn() {
console.log(this.value);
}fn.myCall(obj); // hdove

3.出现的问题

  • 1.无法传值
  • 2.如果fn()有返回值的话,myCall 之后获取不到
Function.prototype.myCall = function (context) {
context.fn = this;
context.fn();
}const obj = {
value: 'hdove'
}function fn() {
return this.value;
}console.log(fn.myCall(obj));
  • 3.call其实就是更改this指向,指向一个Object,如果用户传的是基本类型又或者干脆就不传呢?
  • 4.myCall执行之后,obj会一直绑着fn()

4.统统解决

Function.prototype.myCall = function(context) {
// 1.判断有没有传入要绑定的对象,没有默认是window,如果是基本类型的话通过Object()方法进行转换(解决问题3)
var context = Object(context) || window; /**
在指向的对象obj上新建一个fn属性,值为this,也就是fn()
相当于obj变成了
{
value: 'hdove',
fn: function fn() {
console.log(this.value);
}
}
*/
context.fn = this; // 2.保存返回值
let result = ''; // 3.取出传递的参数 第一个参数是this, 下面是三种截取除第一个参数之外剩余参数的方法(解决问题1)
const args = [...arguments].slice(1);
//const args = Array.prototype.slice.call(arguments, 1);
//const args = Array.from(arguments).slice(1); // 4.执行这个方法,并传入参数 ...是es6的语法用来展开数组
result = context.fn(...args); //5.删除该属性(解决问题4)
delete context.fn; //6.返回 (解决问题2)
return result;
}const obj = {
value: 'hdove'
}function fn(name, age) {
return {
value: this.value,
name,
age
}
}fn.myCall(obj, 'LJ', 25); // {value: "hdove", name: "LJ", age: 25}

二、手动实现Apply

实现了call其实也就间接实现了apply,只不过就是传递的参数不同

Function.prototype.myApply = function (context, args) {
var context = Object(context) || window; context.fn = this; let result = ''; //4. 判断有没有传入args
if (!args) {
result = context.fn();
} else {
result = context.fn(...args);
} delete context.fn; return result;
}const obj = {
value: 'hdove'
}function fn(name, age) {
return {
value: this.value,
name,
age
}
}fn.myApply(obj, ['LJ', 25]); // {value: "hdove", name: "LJ", age: 25}

三、实现Bind

bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用(MDN)

bind和apply的区别在于,bind是返回一个绑定好的函数,apply是直接调用.其实想一想实现也很简单,就是返回一个函数,里面执行了apply上述的操作而已.

不过有一个需要判断的点,因为返回新的函数,要考虑到使用new去调用,并且new的优先级比较高,所以需要判断new的调用,还有一个特点就是bind调用的时候可以传参,调用之后生成的新的函数也可以传参,效果是一样的,所以这一块也要做处理

因为上面已经实现了apply,这里就借用一下,实际上借用就是把代码copy过来

Function.prototype.myBind = function (context, ...args) {
const fn = this
args = args ? args : []
return function newFn(...newFnArgs) {
if (this instanceof newFn) {
return new fn(...args, ...newFnArgs)
}
return fn.apply(context, [...args,...newFnArgs])
}
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,996
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,510
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,353
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,137
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,770
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,848