聊聊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: ...
随机推荐
- css常用布局
1.一列布局 html: <div class="header"></div> <div class="body">< ...
- JavaScript浏览器解析原理
首先,JavaScript的特点是: 1. 跨平台 可以再不同的操作系统上运行. 2. 弱类型 与之相对的是强类型 强类型:在定义变量的时候,需要将变量的数据类型表明.例如:Java 弱类型:定义变量 ...
- Linux下卸载Oracle 11g
第一种方法: 使用oracle自带的runInstaller 卸载 [oracle@VM_0_14_centos deinstall]$ cd $ORACLE_HOME [oracle@VM_0_14 ...
- SQLSERVER 聚集一个表的字段2008及以后,要求支持XML
将以下代码中的TABLE_NAME替换成所需表名称即可. 注意 declare 和set 语句后面不要有 :否则可能执行不成功 declare @S_Column varchar(8000)set @ ...
- day27、28 二十八、项目:选课系统
选课系统 作业要求 角色:学校.学生.课程.讲师 要求: 1. 创建北京.上海 2 所学校 ----> 创建学校 2. 创建linux , python , go 3个课程 , linux\py ...
- easyui dialog 中 panel-body 高度太小出现 滚动条 的原因
easyui dialog 中 panel-body 高度太小出现 滚动条 的原因: dialog 高度比 iframe 高度大79 就可以了 $.editcompanypersoninfo = fu ...
- 为什么不能用 JS 获取剪贴板上的内容?
为什么不能用 JS 获取剪贴板上的内容? 为什么不能用 JS 获取剪贴板上的内容? 发一串口令给朋友朋友复制这串口令,然后访问你的网站你在网站上用 JS 读取朋友剪贴板上的口令根据不同的口令,显示不同 ...
- JavaScript中innerHTML与innerText,createTextNode的区别
innerHTML和innerText 它们都会把元素内内容替换掉,区别在于: innerHTML 会把替换内容里的 HTML 标记解释执行. innerText 会把替换内容里的 HTML 标记原样 ...
- poj2688
#include<iostream> using namespace std; #include<time.h> int m,n; ][]; ][]; typedef stru ...
- ashx获取Oracle数据库图片
using System; using System.Collections.Generic; using System.Linq; using System.Web; using DbLib.db; ...