原生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提 ...
随机推荐
- pybot执行多条用例时,某一个用例执行失败,停止所有用例的执行
问题: pybot执行多条用例时,某一个用例执行失败,停止所有用例的执行 解决办法: pybot -exitonfailure E:\robot\呼送项目\测试用例\基本流程\主流程.txt 参考文章 ...
- Image2Caption
定义 图像标注或语言生成图像问题把计算机视觉与自然语言处理联系在了一起,是广义的人工智能领域的一大难题.通常涉及到特征提取(用cnn提取出图像内部不为人类感知的向量特征)和语言模型建立.为图像提取文字 ...
- MultipartResolver实现文件上传功能
转自:https://www.jb51.net/article/142736.htm springMVC默认的解析器里面是没有加入对文件上传的解析的,,使用springmvc对文件上传的解析器来处理文 ...
- asp.net mvc5 使用百度ueditor 本编辑器完整示例(三)在IIS中多个应用程序使用多个ueditor对象
最近做了一个项目,要求同一类型的多个专业应用程序(网站),但是每个应用程序都需要调用各自当中的ueditor. 步骤: 一.在vs2013中设置每个专业的asp.net mvc 应用程序. 1.配置根 ...
- Extjs 4 MVC中全局配置文件
Extjs 4 Config和Mixins http://kldn.iteye.com/blog/1386622 http://www.fengfly.com/html/JavaScript/ExtJ ...
- 使用MvcMiniProfiler调试ASP.NET MVC网站性能
http://www.cnblogs.com/qiuliang/archive/2011/12/01/2270909.html 使用MiniProfiler给Asp.net MVC和Entity Fr ...
- hdu4786 Fibonacci Tree (最小生成树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4786 题意:给定图的n个点和m条双向边,告诉你每条边的权值.权值为1表示该边是白边,权值为0表示该边为 ...
- Ubuntu 12.04 root默认密码? 如何使用root登录? (转载)
转自:http://www.lupaworld.com/article-219280-1.html 在安装Ubuntu 12.04时并没有设置root的密码,登录的时候也没有使用root账户.当我们使 ...
- 5位ID生成方案
最近在某微信技术群,有人问到如何生成5位唯一数字+字母字符串的算法,要保证生成的字符串唯一,且字符串内部也要唯一. 怎么样,这个需求是不是很简单,也有点特殊呢?简单是指需求简单,特殊是指,字符串长度要 ...
- dllMain函数
Windows在加载DLL的时候,需要一个入口函数,就如同控制台或DOS程序需要main函数.Win32程序需要WinMain函数一样.一些例子中,DLL并没有提供DllMain函数,应用工程也能成功 ...