大家好!!!注册一年多的第一篇博客。

自我介绍: 本人非计算机专业出身,转行进入前端半年时间,写的东西可能观赏性不强,一起进步吧道友们。。。

接下来的一段时间, 我都会不定期整理自己理解的js知识点, 欢迎各路道友吐槽。

进入正题......  (针对新手,老司机不要嘲笑我)

首先, bind/call/apply 这改变this指向的三兄弟我们都很熟悉了, 还有其他改变this指向的方法这里就不多说了哈,要不就跑题了。。。。

你需要知道的前提 : 这三货都是函数原型(Function.prototype)上的方法, 所以只有函数可以调用。

              小白 : “原型是啥?”   每一个构造函数(其实就是普通函数,函数名首字母大写而已)都有一个prototype原型对象,当你引用某个实例对象上的属性时, 会先查找该对象本身有没有该属性,有就用,没有就会去构造这个实例的构造函数的原型上去找,还没有的话就会沿着构造函数的原型对象的__proto__属性往上找......haha, 好像又跑题了, 关于原型链和继承可以自行百度

真的进入正题。。。。。。

它们不是函数上的方法吗, 我们先定义个函数, 后面来改变这个函数的this指向

function out(age, sex, type) {
console.log(age, sex, this.age, this.sex, type);
}

分别输出传入的参数age, sex, type  和   this 上的age , sex,

然后定义个对象, 后面让this指向该对象,  没错,此对象描述的就是我

let  my = {
age : 16,
sex : 'handsome man'
};

先试试bind, 先会用然后再来实现, 由于bind可以传两次参数,你可以这样传

const bindFunction = out.bind(my,50); //this 指向my 不会直接执行 返回一个明确this指向的函数
bindFunction('women','bind'); // 传参执行

还可以这样传,想怎么传就怎么传,只要确保.bind后的第一个参数是你要改变this指向的对象, (如果什么都不传,this指向window)

const bindFunction = out.bind(my); //this 指向my 不会直接执行 返回一个明确this指向的函数
bindFunction('50','women','bind'); // 传参执行

执行后输出 :

50 "women" 16 "handsome man" "bind"

总结一下我们要模拟的bind

1.  函数A调用bind返回一个可执行的函数B, 调用bind时可传参 可不穿参, 不穿参时this指向window

2.  调用B可继续传参, 两次传参合并

3.   new B() 的构造函数依然是A, 而不是B,并且因为new操作符改变this指向的优先级最高,所以如果使用了new操作符,this指向不应该变,就是该是啥是啥(划重点)

上代码 :

Function.prototype.myBind = function (target) { // bind 是 function 上的 方法  this 指向 target
if (typeof this !== 'function') {
throw new TypeError('not a function')
};
const _this = this, // 保存一下this
args = Array.prototype.slice.call(arguments, 1),// arguments是类数组,没有 slice 方法 保存第一次传入的参数
temp = function () {}; // 定义一个中间函数
const f = function () {
return _this.apply(this instanceof temp ? this : (target || window), args.concat([].slice.call(arguments))); // 合并两次传的参数
};
temp.prototype = _this.prototype; // 让temp 的原型 等于 this的原型
f.prototype = new temp(); //f 继承 temp 圣杯继承可以了解下
return f;
};

先正常执行一下myBind:

  const bind1 = this.out.myBind(my, 50);
// const bind2 = new bind1('women','myBind');
  const bind3 = bind1('women','myBind');

结果是:

50 "women" 16 "handsome man" "myBind"

OK , 和bind的输出结果一样

再使用new操作符:

  const bind1 = this.out.myBind(my, 50);
const bind2 = new bind1('women','myBind');
// const bind3 = bind1('women','myBind');

结果是这样:此时this不再指向my, 而是指向new 出来的一个空对象,所以this上没有age和sex两个属性

50 "women" undefined undefined "myBind"

到此bind 我们已经完美模拟出来了  -------- 是不是有点小激动 ----------细心的道友会发现myBind 里 还借用了call 和apply!!! 这还不行啊

自己动手用原生实现 bind/call/apply的更多相关文章

  1. 自己手动用原生实现bind/call/apply

    自己手动用原生实现bind/call/apply:https://www.cnblogs.com/LHLVS/p/10595784.html

  2. 面试官:能解释一下javascript中bind、apply和call这三个函数的用法吗

    一.前言    不知道大家还记不记得前几篇的文章:<面试官:能解释一下javascript中的this吗> 那今天这篇文章虽然是介绍javascript中bind.apply和call函数 ...

  3. bind、apply与call

    bind.apply与call 先说观点:不论是bind.apply还是call,最大的好处就是代码复用. bind 在开发中,我们只有复用代码时,才会出现this指向需要改动的情况. 纵观bind的 ...

  4. Bind、Apply、Call三者的区别

    1)bind与apply.call 的最大区别就是:bind不会立即调用,其他两个会立即调用 var fn = { _int: function(){return 3}, fun: function( ...

  5. 深入理解this和call、bind、apply对this的影响及用法

    首先看一道网易的面试题: var a = { a:"haha", getA:function(){ console.log(this.a); } } var b = { a:&qu ...

  6. bind call apply 的区别和使用

    bind call apply 的区别和使用:https://www.jianshu.com/p/015f9f15d6b3 在讲这个之前要理解一些概念,这些概念很重要,有人说过学会了javascrip ...

  7. 也谈如何实现bind、apply、call

    也谈如何实现bind.apply.call 我们知道,JavaScript的bind.apply.call是三个非常重要的方法.bind可以返回固定this.固定参数的函数包装:apply和call可 ...

  8. javascript 面向对象学习(三)——this,bind、apply 和 call

    this 是 js 里绕不开的话题,也是非常容易混淆的概念,今天试着把它理一理. this 在非严格模式下,总是指向一个对象,在严格模式下可以是任意值,本文仅考虑非严格模式.记住它总是指向一个对象对于 ...

  9. js修改函数内部的this指向(bind,call,apply)

    js修改函数内部的this指向 在调用函数的时候偶尔在函数内部会使用到this,在使用this的时候发现并不是我们想要指向的对象.可以通过bind,call,apply来修改函数内部的this指向. ...

随机推荐

  1. 数据分析之---Python可视化工具

    1. 数据分析基本流程 作为非专业的数据分析人员,在平时的工作中也会遇到一些任务:需要对大量进行分析,然后得出结果,解决问题. 所以了解基本的数据分析流程,数据分析手段对于提高工作效率还是非常有帮助的 ...

  2. ORACLE 快速启动监听及相关服务程序

    windows7 系统下,鼠标移至任务栏右键启动任务管理器->选择服务->点击右下角服务选项 ->选中名称,键盘输入O(大写),快速找到ORACLE相关服务进程 ->将所有的O ...

  3. CORS(跨域资源共享) 的配置

    http://blog.csdn.net/ohyoyo2014/article/details/24863197 兼容情况: 各种新版本的ie10,firefox,opera,safari,chrom ...

  4. 译MassTransit 消息契约

    消息契约 在MassTransit中,使用.NET .NET系统定义消息契约.消息可以使用类和接口来定义,但是,建议类型使用只读属性而不使用行为. 注意:强烈建议使用消息接口的接口,基于多年的经验,具 ...

  5. css3绘制三角形

    将div的宽和高设置为0:利用border-width.border-style.border-color属性绘制不同位置边框的样式.将不需要展示的三角颜色填充为transparent透明即可,就能得 ...

  6. 用 150 行 Python 代码写的量子计算模拟器

    简评:让你更轻松地明白,量子计算机如何遵循线性代数计算的. 这是个 GItHub 项目,可以简单了解一下. qusim.py 是一个多量子位的量子计算机模拟器(玩具?),用 150 行的 python ...

  7. 如何查找Linux服务器上JDK安装路径?

    成功远程到你要部署软件的Linux服务器上.这是第一步. 查看JDK版本:java -version 查看java执行路径:which java 查看JAVA_HOME路径:echo $JAVA_HO ...

  8. MAC下Intellij IDEA常用快捷键

    alt+f7 : 查找在哪里使用 command+alt+f7 : 这个是查找选中的字符在工程中出现的地方,可以不是方法变量类等,这个和上面的有区别的 command+F7 : 可以查询当前元素在当前 ...

  9. Dubbo中消费者初始化的过程解析

    首先还是Spring碰到dubbo的标签之后,会使用parseCustomElement解析dubbo标签,使用的解析器是dubbo的DubboBeanDefinitionParser,解析完成之后返 ...

  10. 基于ELK5.1(ElasticSearch, Logstash, Kibana)的一次整合测试

    前言开源实时日志分析ELK平台(ElasticSearch, Logstash, Kibana组成),能很方便的帮我们收集日志,进行集中化的管理,并且能很方便的进行日志的统计和检索,下面基于ELK的最 ...