聊聊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: ...
随机推荐
- 【spring】-- 手写一个最简单的IOC框架
1.什么是springIOC IOC就是把每一个bean(实体类)与bean(实体了)之间的关系交给第三方容器进行管理. 如果我们手写一个最最简单的IOC,最终效果是怎样呢? xml配置: <b ...
- 在Windows上安装Nexus 3.2.0-01
在Windows上安装Nexus 环境: Windows 7 apache-maven-3.3.9 JDK 1.8 下载Nexus: https://sonatype-download.globa ...
- ECMA Script 6_对象的扩展
对象 1. ES6 允许直接写入变量和函数,作为对象的属性和方法 const foo = 'bar'; /*****************属性的优化********************/ con ...
- 黑盒测试实践——day03
一.任务进展情况 目前基本确定选取的测试工具是Testwriter,测试的web系统还在待定状态,小组成员都在网上搜集相关知识,学习相关的测试技术. 二.存在的问题 Testwriter ...
- postman上传图片时已经添加cookie,但仍显示未登陆
postman上传图片时,已经添加过cookie,但是返回的结果是用户未登陆,如下图所示: 我的解决办法是:清楚cookie code中的cookie 最终的结果如下:成功
- Android 基础知识
system/app 与 system/priv-app Android4.4系统在system目录下新增了priv-app目录,在该目录下的apk一般都是系统核心应用如Launcher.sy ...
- EF Core HasQueryFilter 的小坑
这是今天在实际项目中遇到的一个问题,Entity Framework Core 2.2 生成了下面的 SQL 语句,INNER JOIN 部分丑陋的 SQL 语句让人无法忍受. SELECT TOP( ...
- Python通过简单的文件读写,来实现注册登录
# -*- coding:utf-8 -*- '''''' username = input('请输入您的姓名:') password = input('请输入密码:') with open('get ...
- webrtc如何进行错误恢复
视频的压缩方法:(三种帧) 为了视频尽可能的保持高效,视频数据通过不同的编码进行压缩.以帧为单位进行压缩,按照压缩中的不同作用可分类为:内帧(Intra-frames,I帧),预测帧(Predicti ...
- poj1915
#include<iostream> using namespace std; #define SIZE 305 int vis[SIZE][SIZE]; int sx,sy,ex,ey; ...