原生javascript实现call、apply和bind的方法
var context = {id: 12};
function fun (name, age) {
console.log(this.id, name, age)
}
bind
bind() 方法会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。
原生 bind
1. var a = fun.bind(context, 'bind');
2. a(1); // 12, 'bind', 1 :作为普通函数
3. new a('1'); // undefined, 'bind', '1' :作为构造函数
以上例子可以看出
bind作为普通函数使用时,改变的this的指向,指向context对象;fun函数执行了;传入参数不确定,可以在第一步bind传值,也可以在第二步执行函数fun传值。
bind最为构造函数使用时,不同点是this指向实例的对象。
bind的实现代码
Function.prototype.mybind = function (context) {
if (this && this.constructor !== Function) // 抛错
throw new Error("Function.prototype.mybind - what is trying to be bound is not callable");
// this =>绑定函数 fun
var self = this;
// 获取mybind函数从第二个参数到最后一个参数
var arg = Array.prototype.slice.call(arguments, 1);
function fbound() {
// 普通函数: this => window 构造函数: this => 实例对象
// 获取mybind返回函数传入的函数
var args = Array.prototype.slice.call(arguments);
self.apply(this instanceof self ? this : context, arg.concat(args));
}
var FNOP = function () {};
FNOP.prototype = this.prototype;
fbound.prototype = FNOP.prototype;
return fbound;
}
var a = fun.mybind(context, 'mybind');
a('12') // a: 普通函数
var b = new a(12) // a: 构造函数 b: 实例对象
兼容写法
Function.prototype.bind = Function.prototype.bind || function () {
……
};
call
call() 方法在使用一个指定的 this 值和若干个指定的参数值的前提下调用某个函数或方法。
原生 call
1. fun.call(context, 'call', 2) // 12, call, 2
call 的实现代码
Function.prototype.mycall = function (context) {
if (this && this.constructor !== Function)
throw new Error(this.name + ".mycall is not a function");
context = context || window;
context.fn = this;
var arg = [];
for (var i =1; i< arguments.length; i++) {
arg.push('arguments[' + i + ']');
}
eval('context.fn(' + arg + ')');
delete context.fn;
}
fun.mycall(context, 'mycall', 3); // 12, 'mycall', 3
apply
apply与call的实现原理差不多,只是apply第二个参数是数组;
1. fun.apply(context, ['call', '4']) // 12, call, '4'
Function.prototype.myapply = function (context, arr) {
if (this && this.constructor !== Function)
throw new Error(this.name + ".myapply is not a function");
context = context || window;
context.fn = this;
var arrs = [];
if (arr && arr.constructor === Array) { // 判断第二个参数是数组类型
for (var i =0; i <arr.length; i++) {
arrs.push('arr[' + i + ']');
}
eval('context.fn(' + arrs + ')');
} else if (!arr) { // 第二个参数不传
delete context.fn();
} else { // 第二个参数不是数组类型
throw new Error ("CreateListFromArrayLike called on non-object");
}
delete context.fn;
}
fun.myapply(context, ['myapply', 4]);
原生javascript实现call、apply和bind的方法的更多相关文章
- <JavaScript> call()、apply()、bind() 的用法
其实是一个很简单的东西,认真看十分钟就从一脸懵B 到完全 理解! 先看明白下面: 例 1 obj.objAge; obj.myFun() // 小张年龄 undefined 例 2 shows() ...
- JavaScript中的apply()方法和call()方法使用介绍
1.每个函数都包含两个非继承而来的方法:apply()和call(). 2.他们的用途相同,都是在特定的作用域中调用函数. 3.接收参数方面不同,apply()接收两个参数,一个是函数运行的作用域(t ...
- 原生javascript 获得css样式有几种方法?
css 样式分为行内样式和 外部样式: 1.javascript 获得行内样式 : 可以使用 ele.style."属性名称"(如果遇到属性名称带有"-", ...
- 【THE LAST TIME】this:call、apply、bind
前言 The last time, I have learned [THE LAST TIME]一直是我想写的一个系列,旨在厚积薄发,重温前端. 也是给自己的查缺补漏和技术分享. 欢迎大家多多评论指点 ...
- Javascript中call,apply,bind方法的详解与总结
在 javascript之 this 关键字详解 文章中,谈及了如下内容,做一个简单的回顾: 1.this对象的涵义就是指向当前对象中的属性和方法. 2.this指向的可变性.当在全局作用域时,thi ...
- JavaScript的动态特性(通过eval,call,apply和bind来体现)
JavaScript的动态特性(通过eval,call,apply和bind来体现) JavaScript是一种基于面向对象的.函数式的.动态的编程语言.现在发展到已经可以用在浏览器和服务器端了. 这 ...
- 简单模拟实现javascript中的call、apply、bind方法
目录 引子 隐式丢失 硬绑定 实现及原理分析 总体实现(纯净版/没有注释) 写在最后 引子 读完<你不知道的JavaScript--上卷>中关于this的介绍和深入的章节后,对于this的 ...
- Javascript中call、apply、bind函数
javascript在函数创建的时候除了自己定义的参数外还会自动新增this和arguments两个参数 javascript中函数也是对象,call.apply.bind函数就是函数中的三个函数,这 ...
- JavaScript 之 call apply bind
关键字 this 绑定的方法 this的动态切换,固然为JavaScript创造了巨大的灵活性,但也使得编程变得困难和模糊.有时,需要把this固定下来,避免出现意想不到的情况.JavaScript提 ...
随机推荐
- redis启动时指定配置文件
Redis 启动时指定配置文件需要通过 redis 服务启动才行: 安装服务的教程:http://blog.csdn.net/justinytsoft/article/details/54580919 ...
- vs2008添加消息函数方法
开发MFC时,开发工具VS2008不能像开发工具VC++6.0那样,直接在类文件上右击选择“Add Window Message Handles”来添加消息映射.对于我这个初学者,刚开始一直没找到可以 ...
- HDU 5916 Harmonic Value Description (构造)
题意:给你 n 和 m,求一个1-n的排列,使得∑gcd(Ai,Ai+1) 恰为第 m 小. 析:可以想到最小的就是相邻都互质,然后依次,第 m 小就可以有一个是gcd为 k,然后其他的为1喽. 那 ...
- U3D中碰撞体和刚体的关系
1.刚体是用来接受力作用的组件: 2.碰撞体是碰撞系统用来检测碰撞的组件: 碰撞产生碰撞信息,游戏物体根据碰撞信息生成一个力作用在刚体上,刚体受力后就会产生一个速率,最终在游戏物体的运动体现出来. 也 ...
- Linux系统调用之open(), close() (转载)
转自:http://joe.is-programmer.com/posts/17463.html open函数可以打开或创建一个文件. #include <sys/types.h> #in ...
- 洛谷 P4016 负载平衡问题 【最小费用最大流】
求出平均数sum,对于大于sum的点连接(s,i,a[i]-sum,0),表示这个点可以流出多余的部分,对于小于sum的点连接(i,t,sum-a[i],0)表示这个点可以接受少的部分,然后每个点向相 ...
- bzoj 3779: 重组病毒【LCT+线段树维护dfs序】
%.8lf会WA!!%.8lf会WA!!%.8lf会WA!!要%.10lf!! 和4817有点像,但是更复杂. 首先对于操作一"在编号为x的计算机中植入病毒的一个新变种,在植入一个新变种时, ...
- SQL 初级教程学习(二)
1.SQL 语句从 "Websites" 表中选取头两条记录: SELECT * FROM Websites LIMIT 2; SELECT TOP 50 PERCENT * FR ...
- [USACO 2012 Jan Silver] Bale Share【DP】
传送门:http://www.usaco.org/index.php?page=viewproblem2&cpid=107 没想到太不应该了,真的不应该啊! f[i][j][k]表示前i个包, ...
- CoreText的绘制流程-转
来自:http://blog.sina.com.cn/s/blog_7c8dc2d50101lbb1.html 使用coreText进行文本绘制,需要在工程中添加CoreText.framework, ...