说到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. 删除jar包

    public class TestDelete { private static List<File> files = new ArrayList(); public static voi ...

  2. Oracle存储过程向Hadoop迁移中的问题及方案

    本文记录Oracle存储过程向Hadoop迁移中遇到的问题及响应的解决办法,作为初学者,文中内容有不妥之处欢迎指正, 1.不支持IN中的子查询,Solution,使用INNER JOIN将子查询操作添 ...

  3. JavaScript中作用域和作用域链的简单理解(变量提升)

    通过阅读<JS高级程序设计>这本书,对js中的作用域和作用域链知识有了初步的了解和认识,准备成笔记供大家参考,笔记中字数比较多,但个人认为叙述的挺详细的,所以希望读者耐心看.再者,本人了解 ...

  4. Scrapy 框架

    1. 基本使用 1.1 定义及安装 为了爬取网站数据,提取结构性数据而编写的应用框架 scrapy组件工作流程 引擎首先会将爬虫文件中的起始url获取,并且提交到调度器中.如果需要从url中下载数据, ...

  5. 创建phpinfo(PHP探针)查看自己服务器空间php详细信息

    创建phpinfo(PHP探针)查看自己服务器空间php详细信息 <?phpphpinfo();?> 保存,然后更改文件名为phpinfo.php 放到你域名根目录,然后访问:http:/ ...

  6. 搭建自己的Webpack项目

    五,搭建自己的Webpack项目  https://www.jianshu.com/p/42e11515c10f

  7. Java之为何配置环境变量

    一.不要问一个程序员为什么命名是基础零(^_^) 二.Java为什么跨平台: 因为有java虚拟机,一个程序的运行必然要依赖于系统,java的跨平台是因为java虚拟机jvm把不同平台编写的代码编译成 ...

  8. __x__(19)0907第四天__ HTML5 文本标签 及 样式

    strong 表语义上的强调, em 表示语气上的强调: <strong>警告:离僵尸远点!</strong> 世界末日了,因为僵尸是<em>有毒的</em& ...

  9. Wireshark简单使用教程2——附视频

    视频链接https://www.bilibili.com/video/av35336089/ 目录 对抓取的流量包进行简单的说明 Wireshark的捕获过滤器和显示过滤器 内容 1.对抓取的流量包进 ...

  10. tp5 查询单个字段的值

    $num_lastday = Db::name('test_wx') ->where('num','=',$data['num']) ->order('time desc') ->l ...