博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
模拟js中的call、apply和bind的实现
阅读量:6712 次
发布时间:2019-06-25

本文共 2727 字,大约阅读时间需要 9 分钟。

一、call和apply的特点

  • 可以改变我们当前函数的this指向
  • 还会让当前函数执行

var person = {    value : 1}function bar() {    console.log(this.value)}// 如果不对this进行绑定执行bar() 会返回undefined,this指向windowbar.call(person) // 1复制代码

试想一下当调用call的时候也就类似于

var person = {    value: 1,    bar: function() {        console.log(this.value)    }}person.bar() // 1复制代码

这样就把 this 指向到了 person上,但是这样给 person 对象加了一个属性,不太合适,不过不要紧,执行完删除这个属性就可以实现了。

也就是说步骤其实是这样的

  1. 将函数设为对象的属性
  2. 执行这个函数
  3. 删除这个函数

1、call模拟实现

Function.prototype.call = function(context){    context = context ? Object(context) : window;//不传递context默认为window    context.fn = this;//this也就是调用call的函数    let args = [...arguments].slice(1);    let r = context.fn(...args);    delete context.fn;    return r;}复制代码

2、apply模拟实现

apply的方法和 call 方法的实现类似,只不过是如果有参数,以数组形式进行传。

Function.prototype.apply= function(context,args){    context = context ? Object(context) : window;//不传递context默认为window    context.fn = this;    if(!args){        return context.fn();    }    let r = context.fn(...args);    delete context.fn;    return r;}复制代码

二、bind的特点

  • bind方法可以绑定this指向  绑定参数
  • bind方法返回一个绑定后的函数(高阶函数)
  • 调用绑定后的方法,会让原方法执行
  • 如果绑定的函数被new了,当前函数的this就是当前的实例
  • new出来的结果,可以找到原有类的原型

1、bind方法模拟实现第一步

用法:

let obj = {    name:'gjf'}function fn(){    console.log(this.name)}let bindFn = fn.bind(obj); //返因一个绑定后的方法findFn() //用绑定后的方法,让原方法执行复制代码

实现:

Function.prototype.bind = function(context){    let that = this;    return  function(){        return that.apply(context);        }}复制代码

这样实现了最简单的改变this指向的bind,但是这样还远远不够,因为bind还可以绑定参数;

2、bind方法模拟实现第二步

方法传参可以分两批传,一批可以先在bind方法里面先绑定好,另一批在调用的时候传参,例如以下示例;

用法:

let obj = {    name:'gjf'}function fn(name,age){    console.log(this.name+'养了一只'+name+age+'岁了')}let bindFn = fn.bind(obj,'猫'); //返因一个绑定后的方法findFn(8) //用绑定后的方法,让原方法执行复制代码

实现:

Function.prototype.bind = function(context){    let that = this;    let bindArgs = Array.prototype.slice.call(argument,1)//['猫']    return  function(){        let args = Array.prototype.slice.call(argument);        return that.apply(context,bindArgs.concat(args));        }}复制代码

3、bind方法模拟实现第三步

调用bind返回的函数除了可以直接调用,还可以把函数当成一个类来调用;原函数上绑定了属性,new出来的实例上能否访问。

用法:

fn.prototype.flag = '哺乳类'; //原函数上绑定了属性let findFn = fn.bind(obj,'猫');let instance = new findFn(8);//如果绑定的函数被new了,当前函数的this就是当前的实例console.log(instance.flag) //undefined复制代码

实现:

Function.prototype.bind = function(context){    let that = this;    let bindArgs = Array.prototype.slice.call(argument,1)//['猫']    function Fn(){} //Object.create的原理    function fBound(){        let args = Array.prototype.slice.call(argument);        return that.apply(this instanceof fBound ? this:context,bindArgs.concat(args));        }    Fn.prototype = this.prototype;    fBound.prototype = new Fn();    return fBound;}复制代码

这里,我们js里的三种改变this指向的方法就实现啦。。。。。

转载地址:http://hmolo.baihongyu.com/

你可能感兴趣的文章
安装python的easy_install和pip
查看>>
android SQLite
查看>>
Apache for Load Banlance
查看>>
Sublime Text 2 快捷键用法大全
查看>>
放弃redis使用mongodb做任务队列支持增删改管理
查看>>
20几岁要懂的处世心理学
查看>>
G口与S口的区别
查看>>
linux xen安装
查看>>
apache2.4.16 显示真实ip
查看>>
甲骨文拒绝SAP 2.72亿美元赔偿要求重审
查看>>
Springmvc中@ResponseBody和@RequestBody的使用
查看>>
H3C设备之 NAT SERVER
查看>>
FLEX3中应用CSS完全详解手册
查看>>
Windows7添加usb3.0驱动
查看>>
模式——工程化实现及扩展(设计模式Java 版)
查看>>
如何干净的清除Slave同步信息
查看>>
Oracle动态采样学习
查看>>
借助开源工具高效完成Java应用的运行分析
查看>>
Transparent Huge Pages相关概念
查看>>
浅谈RAID和LVM
查看>>