说到call、apply、bind,前端的胖友可是不陌生。以下就从几个方面分别聊聊它们。

是什么?(what?)

实际上它们真正的样子是这样的:

  • Function.prototype.call(thisArg, arg1, arg2, ...)
  • Function.prototype.apply(thisArg, [arg1, arg2, ...])
  • Function.prototype.bind(thisArg, arg1, arg2, ...)

它们几个的作用都是改变this的指向。

三者有什么区别?

  • .call(thisArg, arg1, arg2, ...)和.apply(thisArg, [arg1, arg2, ...])的区别只是后者的参数列表以数组形式传入。

  • .bind()与另外两个的区别则是前者改变this,不立即调用函数;而后者改变this,立即调用函数。

非严格模式和严格模式的注意点

以下例子在非严格模式下,

// 注释的是各个情况this的指向
let test = {
foo: function(...arg) {
console.log(this);
console.log([...arg]);
}
}
test.foo();
test.foo.call(null, 1, 2);//this->window
test.foo.call('', 1, 2);// this->string
test.foo.call(undefined, 1, 2); //this->window
test.foo.apply(null, [1, 2]);//this->window
test.foo.apply('', [1, 2]);// this->string
test.foo.apply(undefined, [1, 2]);//this->window
test.foo.bind(null, 1, 2);
test.foo.bind('', 1, 2);
test.foo.bind(undefined, 1, 2);

在严格模式下,

// 注释的是各个情况this的指向
'use strict'
let test = {
foo: function(...arg) {
console.log(this);
console.log([...arg]);
}
}
test.foo();
test.foo.call(null, 1, 2);//this->null
test.foo.call('', 1, 2);// this->
test.foo.call(undefined, 1, 2); //this->undefined
test.foo.apply(null, [1, 2]);//this->null
test.foo.apply('', [1, 2]);//this->
test.foo.apply(undefined, [1, 2]);// this->undefined
test.foo.bind(null, 1, 2);
test.foo.bind('', 1, 2);
test.foo.bind(undefined, 1, 2);

怎么模拟实现三者呢?

那么为什么要模拟实现呢?

  • 更加理解三者改变this指向的原理
  • 兼容一些浏览器
.mycall()的实现
Function.prototype.mycall = function(context, ...arg) {
// 改变this指向
// 1. 通过this获取函数,
var context = context || window;
context.fn = this;
// 执行函数
context.fn(...arg);
// 2. 删除函数
delete context.fn;
}
var foo = {
value: 'foo'
}
var bar = function(name, age) {
console.log(name);
console.log(age);
console.log(this.value);
console.log(this);
}
// bar.mycall(foo, 'zenquan', 23);
bar.mycall(null, 'zenquan', 23)
.myapply()的实现
Function.prototype.myapply= function(context, [...arg]) {
// 改变this指向
// 1. 通过this获取函数,
var context = Object(context) || window;
context.fn = this;
var result = null;
// 执行函数
if(![...arg]) {
result = context.fn();
}else {
result = context.fn(...arg);
}
// 2. 删除函数
delete context.fn;
return result;
}
var bar = function(name, age) {
console.log(name);
console.log(age);
// console.log(this.value);
console.log(this);
}
bar.myapply(null, ['zenquan', 23]);
.mybind()的实现
Function.prototype.mybind = function (context) {

    if (typeof this !== "function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
} var self = this;
var args = Array.prototype.slice.call(arguments, 1); var fNOP = function () {}; var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
} fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}

Emmm,说好了聊聊故事,结果还是说了一大堆干巴巴的知识,可能我是个不会讲故事的标题党吧。

聊聊call、apply、bind的故事的更多相关文章

  1. call,apply,bind的用法

    关于call,apply,bind这三个函数的用法,是学习javascript这门语言无法越过的知识点.下边我就来好好总结一下它们三者各自的用法,及常见的应用场景. 首先看call这个函数,可以理解成 ...

  2. JavaScript中call,apply,bind方法的总结。

    why?call,apply,bind干什么的?为什么要学这个? 一般用来指定this的环境,在没有学之前,通常会有这些问题. var a = { user:"追梦子", fn:f ...

  3. call(),apply(),bind()与回调

    1.call(),apply(),bind()方法 JavaScript 中通过call或者apply用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定 ...

  4. JS 的 call apply bind 方法

    js的call apply bind 方法都很常见,目的都是为了改变某个方法的执行环境(context) call call([thisObj[,arg1[, arg2[,   [,.argN]]]] ...

  5. javascript-this,call,apply,bind简述2

    上节我们一起研究了this这个小兄弟,得出一个结论,this指向调用this所在函数(或作用域)的那个对象或作用域.不太理解的朋友可以看看上节的内容,这次我们主要探讨一下call(),apply(), ...

  6. javascript-this,call,apply,bind简述1

    最近在系统的学习面向对象方面的知识,遇到的最大拦路虎就数this的指向,call,apply,bind函数的使用,单独抽出一天时间把这几个烦人的家伙搞定,去学习更深入的内容. 首先介绍一下this的一 ...

  7. call,apply,bind方法的总结

    why?call,apply,bind干什么的?为什么要学这个? 一般用来指定this的环境,在没有学之前,通常会有这些问题. var a = { user:"追梦子", fn:f ...

  8. JavaScript中call,apply,bind方法的总结

    原文链接:http://www.cnblogs.com/pssp/p/5215621.html why?call,apply,bind干什么的?为什么要学这个? 一般用来指定this的环境,在没有学之 ...

  9. call, apply,bind 方法解析

    call(), apply(),bind() 三者皆为Function的方法 call(),apply()的作用是调用方法,并改变函数运行时的context(作用上下文) bind() 的作用是引用方 ...

  10. JS中call,apply,bind方法的总结

    why?call,apply,bind干什么的?为什么要学这个? 一般用来指定this的环境,在没有学之前,通常会有这些问题. var a = { user: "小马扎", fn: ...

随机推荐

  1. 阿里云负载均衡SSL证书配置(更新)

    阿里云负载均衡及应用防火墙SSL证书配置 转载请注明地址:http://www.cnblogs.com/funnyzpc/p/8908461.html 好久了呢,距上篇博客的这段时间中:考试.搬家.工 ...

  2. 潭州课堂25班:Ph201805201 tornado 项目 第八课 增加喜欢功能(课堂笔记)

    tornado 相关说明 新增一个页面,用来做图片收藏, 还要在 account.py 创建一个数据库表,记录用户喜欢的图片,哪些图片用户疯狂传奇 cd 到 项目目录下,执行数据库更新 alembic ...

  3. Emgucv - ImageBox控件

    C#的Winform中用来显示图片的控件是PictureBox,而Emgucv中显示图片用的是ImageBox. 1.ImageBox属性 在WinForm中,单击ImageBox控件,右击查看属性页 ...

  4. linux 文件属性(转)

    1.  文件类型 - 普通文件 d 目录文件 l 链接文件 b 块设备文件 c 字符型设备文件 s socket文件 p 管道类型文件 块设备文件主要是指慢速设备,比如hd硬盘,数据主要是分块存储,所 ...

  5. BZOJ 5104

    这个模数比较有趣 可以求出 $\sqrt{5}$ 然后就可以做了 $f_n=\dfrac{\sqrt{5}}{5}[(\dfrac{\sqrt{5}+1}{2})^n-(\dfrac{1-\sqrt{ ...

  6. php 获取 两个时间戳之间 相隔 【多少年】 【 多少个月】 【多少天】 【 多少个小时】 【多少分】【 多少秒 】

    /** * 返回两个时间的相距时间,*年*月*日*时*分*秒 * @param int $one_time 时间戳一 大的时间戳 * @param int $two_time 时间戳二 小的时间戳 * ...

  7. Spring-day02

    Annotation复习:1,Annotation:作为类型的元数据; 1,给类型加标记; 2,annotation可以添加各种类型的属性;2,Annotation的上的标记: 1),target:标 ...

  8. python全栈开发 * 线程队列 线程池 协程 * 180731

    一.线程队列 队列:1.Queue 先进先出 自带锁 数据安全 from queue import Queue from multiprocessing import Queue (IPC队列)2.L ...

  9. nodejs----微信注册测试号获取token

    var PORT=8081; //监听8080端口号 var http=require('http'); var qs=require('qs'); var TOKEN='yezhenxu'; //必 ...

  10. Java常用类库 读书笔记 一

    1.String Buffer 类 String 类所表示的字符串有一个局限就是字符串常量一旦声明则不可改变,只有内存地址的指向可以改变,如果要频繁修改字符串,需要使用String Buffer 类. ...