聊聊call、apply、bind的故事
说到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的故事的更多相关文章
- call,apply,bind的用法
关于call,apply,bind这三个函数的用法,是学习javascript这门语言无法越过的知识点.下边我就来好好总结一下它们三者各自的用法,及常见的应用场景. 首先看call这个函数,可以理解成 ...
- JavaScript中call,apply,bind方法的总结。
why?call,apply,bind干什么的?为什么要学这个? 一般用来指定this的环境,在没有学之前,通常会有这些问题. var a = { user:"追梦子", fn:f ...
- call(),apply(),bind()与回调
1.call(),apply(),bind()方法 JavaScript 中通过call或者apply用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定 ...
- JS 的 call apply bind 方法
js的call apply bind 方法都很常见,目的都是为了改变某个方法的执行环境(context) call call([thisObj[,arg1[, arg2[, [,.argN]]]] ...
- javascript-this,call,apply,bind简述2
上节我们一起研究了this这个小兄弟,得出一个结论,this指向调用this所在函数(或作用域)的那个对象或作用域.不太理解的朋友可以看看上节的内容,这次我们主要探讨一下call(),apply(), ...
- javascript-this,call,apply,bind简述1
最近在系统的学习面向对象方面的知识,遇到的最大拦路虎就数this的指向,call,apply,bind函数的使用,单独抽出一天时间把这几个烦人的家伙搞定,去学习更深入的内容. 首先介绍一下this的一 ...
- call,apply,bind方法的总结
why?call,apply,bind干什么的?为什么要学这个? 一般用来指定this的环境,在没有学之前,通常会有这些问题. var a = { user:"追梦子", fn:f ...
- JavaScript中call,apply,bind方法的总结
原文链接:http://www.cnblogs.com/pssp/p/5215621.html why?call,apply,bind干什么的?为什么要学这个? 一般用来指定this的环境,在没有学之 ...
- call, apply,bind 方法解析
call(), apply(),bind() 三者皆为Function的方法 call(),apply()的作用是调用方法,并改变函数运行时的context(作用上下文) bind() 的作用是引用方 ...
- JS中call,apply,bind方法的总结
why?call,apply,bind干什么的?为什么要学这个? 一般用来指定this的环境,在没有学之前,通常会有这些问题. var a = { user: "小马扎", fn: ...
随机推荐
- 阿里云服务器端配置TensorFlow & jupyter
在阿里云上搭建爬取某信的公众号文章的程序时,发现需要验证码验证,技穷之后考虑做一个验证码识别程序,所以开始在服务器上搭建机器学习平台,背景,服务器上已经有其他应用在跑着了,所以不想停服,初始环境:ce ...
- yum clear all无反应
卸载重装yum 操作系统版本:centos7 [root@linux-node3 ~]# uname -r 3.10.0-514.el7.x86_64 一.将现有的yum源卸载 [root@linux ...
- NEO智能合约开发(二)再续不可能的任务
NEO智能合约开发中,应用合约比较简单,是的你没看错,应用合约比较简单. 应用合约三部曲,发布.调用.看结果.除了看结果工具比较缺乏,发布调用neogui最起码可以支撑你测试. 鉴权合约比较麻 ...
- PYTOGO之旅——环境搭建
Go 语言支持以下系统: Linux FreeBSD Mac OS X(也称为 Darwin) Windows 安装包下载地址为:https://golang.org/dl/. 如果打不开可以使用这个 ...
- jmeter实例介绍
JMeter基础之一 一个简单的性能测试 测试需求: 1)测试目标网站是fnng.cnblogs.com 和 tt-topia.rhcloud.com 2)测试目的是该网站在负载达到20 QPS 时 ...
- Java虚拟机一 运行时数据区(栈、堆、方法区等)
Java虚拟机的内存管理主要分两点:内存分配以及内存回收.· 一.内存分配图: 注: 所占区域的大小与实际的内存大小比例并无直接关系. 解读: 1.如图,分成两种颜色的内存区域,其中蓝色的是线程隔离的 ...
- mobile_点透_传透_touch-action
点透(传透) <meta name="viewport" content="width=device-width, initial-scale=1.0, user- ...
- react_app 项目开发 (7)_难点集合
/src/App/Admin/Header 布局 import {Row, Col} from "antd" <div className="header_box& ...
- window iis重启
WINDOWS server 任务计划实现定时自动重启IIS编写批处理文件IIS.bat@echo offnet stop iisadmin /yesnet start iisadminnet sta ...
- jquery各版本
各版本下载: https://www.jb51.net/zt/jquerydown.htm