apply()和call()

虽然在一个独立的函数调用中,根据是否是strict模式,this指向undefined或window,不过,我们还是可以控制this的指向的!
要指定函数的this指向哪个对象,可以用函数本身的apply方法,它接收两个参数,第一个参数时在其中运行函数的作用域,第二个参数是Array的实例,也可以是arguments对象。

另一个与apply()类似的方法是call(),唯一区别是:apply()把参数打包成Array再传入,call()把参数按顺序传入。比如调用Math.max(3, 5, 4),分别用apply()和call()实现如下:Math.max.apply(null, [3, 5, 4]); Math.max.call(null, 3, 5, 4); 对普通函数调用,我们通常把this绑定为null。

function sum(num1, num2){
return num1 + num2;
}
function callSum(num1, num2){
return sum.call(this, num1, num2);
}
function callSum1(num1, num2){
return sum.apply(this, arguments);
}
function callSum2(num1, num2){
return sum.apply(this, [num1, num2]);
}
console.log(callSum(10,10)); //20
console.log(callSum1(10,10));//20
console.log(callSum2(10,10));//20

apply和call常被用来扩展函数赖以运行的作用域。

window.color = 'red';
var o = {color:'blue'};
function sayColor(){
console.log(this.color);
}
sayColor(); //red
sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //blue

在上面的例子中,定义了一个全局函数sayColor,在全局作用域中调用时,对this.color的求值会转换成对window.color的求值,sayColor.call(this)和sayColor.call(window)是两种显示地在全局作用域中调用函数的方式,结果都会显示"red",但是当运行sayColor.call(o)时,函数的执行环境就不一样了,此时函数内的this对象指向了o,于是结果显示"blue"。

使用call()和apply()来扩充作用域的最大好处就是对象不需要与方法有任何耦合关系。

function getAge(){
var y = new Date().getFullYear();
return y - this.birth;
}
var xiaoming = {
name: '小明',
birth: 1990,
age: getAge
};
console.log(xiaoming.age()); //27
console.log(getAge.apply(xiaoming,[])); //27

bind()

bind()是ES5新增的方法,这个方法的主要作用就是将函数绑定到某个对象
  当在函数f()上调用bind()方法并传入一个对象o作为参数,这个方法将返回一个新的函数。以函数调用的方式调用新的函数将会把原始的函数f()当做o的方法来调用,传入新函数的任何实参都将传入原始函数。

function f(y){
return this.x + y; //这个是待绑定的函数
}
var o = {x:1};//将要绑定的对象
var g = f.bind(o); //在函数f()上调用bind()方法并传入一个对象o作为参数,得到一个新的函数g
g(2);//3

上面的代码就是把原始的函数f()当做o的方法来调用 ,传入实参都将传入原始函数。

var o={
x:1
f:function(y){
return this.x + y; //y=2
}
}

bind()方法不仅是将函数绑定到一个对象,它还附带一些其他应用:除了第一个实参之外,传入bind()的实参也会绑定到this,这个附带的应用是一种常见的函数式编程技术,有时也被称为'柯里化'(currying)。

var sum = function(x,y){
return x+y;
}
var succ = sum.bind(null,1); //在函数sum上调用bind()方法并传入一个对象window,得到新的函数succ,并且还到了一个实参到该对象中
succ(2); //3,x绑定到1,并传入2作为实参y function f(y,z){
return this.x + y + z; //this指向当前调用的对象或Window
}
var g = f.bind({x:1},2);
g(3); //6,this.x绑定到1,y绑定到2,z绑定到3

实现call

1,将函数设为对象的属性

2,执行&删除这个函数

3,指定this到函数并传入给定参数执行函数

4,如果不传入参数,默认指向为window

Function.prototype.myCall = function(context){
context.fn = this;
let args = [];
for(let i=1,len = arguments.length;i<len;i++){
args.push(arguments[i]);
}
context.fn(...args);
let result=context.fn(...args);
delete context.fn;
return result;
}

实现apply方法

Function.prototype.myApply = function(context,arr){
var context = Object(context) || window;
context.fn = this;
var result;
if(!arr){
result = context.fn();
}else{
var args = [];
for(var i=0,len=arr.length;i<len;i++){
args.push("arr[" + i + "]");
}
result = eval("context.fn(" + args +")");
}
delete context.fn;
return result;
}

apply、call和bind的更多相关文章

  1. 动态作用域与this +apply和call +bind

    词法作用域是一套关于引擎如何寻找变量以及会在何处找到变量的规则. (函数作用域和块作用域) JavaScript 中的作用域就是词法作用域,也就是静态作用域,由定义代码决定 动态作用域似乎暗示有很好的 ...

  2. js call apply caller callee bind

    call apply bind作用类似.即调用一个对象的一个方法,以另一个对象替换当前对象. call 语法:call([thisObj[,arg1[, arg2[,   [,.argN]]]]]) ...

  3. JavaScript方法call,apply,caller,callee,bind的使用详解及区别

    一.call 方法 调用一个对象的一个方法,以另一个对象替换当前对象(其实就是更改对象的内部指针,即改变对象的this指向的内容). 即  “某个方法”当做“指定的某个对象”的“方法”被执行. Js代 ...

  4. 前端见微知著JavaScript基础篇:你所不知道的apply, call 和 bind

    在我的职业生涯中,很早就已经开始使用JavaScript进行项目开发了.但是一直都是把重心放在了后端开发方面,前端方面鲜有涉及.所以造成的一个现象就是:目前的前端知识水平,应付一般的项目已然是足够的, ...

  5. JS中的call()和apply()方法和bind()

    1.方法定义 call方法: 语法:call([thisObj[,arg1[, arg2[,   [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象. 说明: call ...

  6. 浅谈JavaScript中的apply,call和bind

    apply,call,bine 这三兄弟经常让初学者感到疑惑.前两天准备面试时特地做了个比较,其实理解起来也不会太难. apply MDN上的定义: The apply() method calls ...

  7. JavaScript 构造函数 prototype属性和_proto_和原型链 constructor属性 apply(),call()和bind() 关键字this

    1.构造函数: 通常构造函数首字母需要大写,主要是为了区别ECMAScript的其它函数.(高程三 P145) 构造函数与其他函数的唯一区别,就在于调用它们的方式不同.只要通过new来调用,任何函数都 ...

  8. 彻底理解了call()方法,apply()方法和bind()方法

    javascript中的每一个作用域中都有一个this对象,它代表的是调用函数的对象.在全局作用域中,this代表的是全局对象(在web浏览器中指的是window).如果包含this的函数是一个对象的 ...

  9. apply,call和bind的用法区别

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. this、apply/call、bind、闭包、函数、变量复制

    一.实际场景中抽象出的一个问题 下面this各指向什么? var a = { b: function() { console.log(this); }, f: function() { var c = ...

随机推荐

  1. Microsoft Jet 数据库引擎 SQL 和 ANSI SQL 的比较

    http://westlife063.blog.163.com/blog/static/129942096201052591210384/   Microsoft Jet 数据库引擎 SQL 和 AN ...

  2. C++面向对象多线程入门

    第1节   背景 为了更好的理解多线程的概念,先对进程,线程的概念背景做一下简单介绍. 早期的计算机系统都只允许一个程序独占系统资源,一次只能执行一个程序.在大型机年代,计算能力是一种宝贵资源.对于资 ...

  3. easyui常用属性

    属性分为CSS片段和JS片段. CSS类定义:1.div easyui-window        生成一个window窗口样式.      属性如下:                   1)mod ...

  4. Java数字签名算法--RSA

    签名具有的特性: 安全性 抗否认性 数字签名:带有密钥(公钥.私钥)的消息摘要算法(使用私钥进行签名,使用公钥进行验证) 数字签名算法:RSA.DSA.ECDSA 数字签名特性: 验证数据完整性 认证 ...

  5. AHK教程 - imsoft.cnblogs

    转自:小弗兰茨 AHK,就是传说中的 Auto Hot Key .什么?没有听说过?那么很正常……它运行在Windows下.总之,AHK可以赋予你对你的电脑的无与伦比的控制力.一些人想要在MM面前展示 ...

  6. (1)变量、常量、程序交互、数据类型、bool、基本运算符

    什么是变量 变量由变量名和变量值组成 name = 'Alex Li'  这个算式就是将一个值赋予给变量,也就是声明变量的意思 name 就是一个变量,也是一个变量的名字 'Alex Li' 就是一个 ...

  7. java二叉树排序实现

    原创:转载请注明出处 目的:想用java实现二叉树排序算法 思想:利用java中面向对象的思想,即: Tree:类 树根Tree:root //static所属于每一个Tree 左节点Tree:lef ...

  8. MySQL--MODIFY COLUMN和ALTER COLUMN

    =================================================== 在修改列时,可以使用ALTER TABLE MODIFY COLUMN  和ALTER TABL ...

  9. ImportTsv-HBase数据导入工具

    一.概述 HBase官方提供了基于Mapreduce的批量数据导入工具:Bulk load和ImportTsv.关于Bulk load大家可以看下我另一篇博文. 通常HBase用户会使用HBase A ...

  10. IEPNGFix 解决IE6支持PNG透明问题

    IE6本身是支持索引色透明度(PNG8)格式,但不支持真彩色透明度(PNG24)格式. 使用IE PNG Fix 2.0可以完美解决IE6支持PNG透明问题,而且支持背景定位和重复属性. IE PNG ...