先介绍每个的语法:

1. bind()

语法:fn.bind(thisObj[, arg1[, arg2[, ...]]])

fn:是想要改变this指向的函数

thisObj:表示fn中this指针指向的新对象。可选。

作用:改变this指向,并返回一个函数。

后面的参数:看似复杂,实际上就相当于一个一个列出来,即fn.bind(thisObj, arg1, arg2, ...)。参数也可以为单独的数组,例如:fn.bind( thisObj,1,2,[3,34] );。可选

注意: 这个方式返回的是函数,并不像call和apply一样直接执行完成。要想执行必须后面再用 () 括号调用。这个方法在ie6-8不支持。并且ie9不支持严格模式。

     bind()也可以这样使用:

var newFn=fn.bind(thisObj);
newFn(arg1,arg2, ...);

   这样每次调用newFn,这个函数里的this都是指向的是thisObj。

2. apply()

语法:fn.apply(thisObj, [argsArray])

fn:是想要改变this指向的函数

thisObj:表示fn中this指针指向的新对象。可选

后面的参数:只能是一个数组。可选

注意:如果thisObj不指定或者thisObj为null或者undefined,那么thisObj默认为window对象。如果thisObj为字符串,数字,布尔值这些原始数据类型(这里不包括null和undefined)。那么此时的this会指向改原始数据类型包装的对象。例如:

var obj={
say:function(){
console.log(this);
}
}
obj.say.apply('123')

  执行之后,this的值为:

  其它的可以自行去举例体会。

3. call()

语法:fn.call(thisObj, arg1, arg2, ...)

fn:是想要改变this指向的函数

thisObj:表示fn中this指针指向的新对象。可选

后面的参数:一个一个列出来。可选

注意:thisObj的注意事项和上面apply的一样。apply与call的区别就是接收的参数的区别,call是一个一个列出来,apply是一个数组。

当参数确定时可以考虑用call,如果参数不确定时建议用apply。如果想多次使用改变this指针指向的函数,可考虑用bind 。

前三个方法的作用都是为了改变函数里this指针的指向。

关于不同情况下this指针指向,请看我的这篇文章:深入理解this指针指向

4. caller()

作用:返回调用指定函数的函数

语法:fn.caller()

注意:如果一个函数fn是在全局作用域内被调用的,则fn.caller为null。相反,如果一个函数fn是在另外一个函数作用域内被调用的,则fn.caller指向调用它的那个函数。而且caller只有在函数执行时才有效

    该特性是非标准特性,请尽量不要在生产环境中使用它。这是MDN上说的,但是caller被所有主流浏览器兼容

例子

function add(){
function bdd(){
console.log(bdd.caller)
}
bdd();
  console.log(add.caller);
}
add()

    最后输出的结果是:

  因为add这个函数是在全局作用于内被调用,所以是null,而bdd是在add函数中被调用,所以是整个add函数。

上面四个都是继承至Function。

下面的callee是函数参数集合arguments里的一个属性

5. callee

作用:用于引用该函数的函数体内当前正在执行的函数

语法:arguments.callee

注意:在es5的严格模式下arguments.callee被删除了。但是普通模式下兼容性挺好的。

 例子:

function add(){
function bdd(){
console.log(arguments.callee)
}
bdd();
console.log(arguments.callee)
}
add()

  结果分别是:

  第一个console中,当前正在执行的函数是bdd,所以显示出来是bdd函数。第二个console,当前正在执行的是add,所以是add函数。


下面是例子:

call、apply:

var obj = {age:10};
function fn() {
console.log(this);
console.log(this.age);
}
fn();
fn.call(obj);
fn.apply(obj);

来分析一下:

(1) 当执行到fn()时,fn是window直接调用,是全局函数,所以此时this指向的是window。因此this.age是undefined

(2) 当执行到fn.call(obj)时,call改变了fn函数中this的指向,此时this指向了obj,所以此时this.age是10;

(3) 这里apply和call没区别,所以结果也是一样。

call、apply妙用:

(1) 求数组中的最大,最小值(number类型)

var num=[8,99,1,46,13,12,11,19,26];
var max=Math.max.apply(null,num);//
var min=Math.min.apply(null,num);//

(2) 类似数组的contact方法:

var arr1 = ["a", "777","b","c"];
var arr2 = ["n", "m", 77];
Array.prototype.push.apply(arr1, arr2);
console.log(arr1);//["a", "777", "b", "c", "n", "m", 77]

再来一道简单的面试题:

var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
console.log('1.' + this.name);//第一个console
return function(){
return this.name;
};
}
};
var func = object.getNameFunc();
console.log('2.' + func());//第二个console
console.log('3.' + func.call(object));//第三个console
console.log('4.' + func.apply(object));//第四个console

我们来分析一下这道题:

(1) 当执行到 var func = object.getNameFunc(); 这句代码时,会执行第一个console,这时候,getNameFunc()函数由于是通过object直接调用,那么这个函数中的this就是指向的object,所以第一个console输出的是  1. My  Object   。然后这个函数返回了一个匿名函数。

(2) 当执行到第二个console时,由于上一句执行完之后,func是一个function,但还未执行,this指向不明确。这时候执行这个函数时,func是通过window直接调用,所以,此时func函数中的this指向的是window。所以第二个语句的输出是 2. The  Window。

(3) 执行到第三个console时,本来func中的this是指向window,但是通过call,改变了这个this的指向,call(object)告诉我们这时候,this指向的是object。所以第三个console输出的是  3. My  Object

(4) 由于call和apply只有传入参数的区别,所以这里的call和apply是一样的效果,所以这里func这里的this指向的还是object。所以第四个console输出的是  4. My  Object

bind:

var a ={
name : "bajie",
fn : function (a,b) {
      console.log(this.name);
console.log( a + b);
}
}
var b = a.fn.bind(a);
b(1,2);

又来分析分析:

(1)当执行到 var b = a.fn.bind(a); 的时候,这时的b就是通过bind函数返回的一个函数,而且这时b函数里的this指向的是a这个对象。

(2) 当调用b函数时,这时有人可能会说直接调用b的是window,所以这时this应该指向window。但是实际上,b函数里的this已经通过bind修改成指向a了,所以这里不管执行多少次,this都还是指向a。所以最终执行后结果是bajie   3;

(3) 这里b函数也可以使用 window.b(1,2); 这样使用,结果还是一样的。使用了bind()之后并没有受到window的影响!!!这里需要注意。。。

bind,apply,call,caller,callee还傻傻分不清楚?的更多相关文章

  1. js apply/call/caller/callee/bind使用方法与区别分析

    一.call 方法 调用一个对象的一个方法,以另一个对象替换当前对象(其实就是更改对象的内部指针,即改变对象的this指向的内容). Js代码 call([thisObj[,arg1[, arg2[, ...

  2. js经验点滴js apply/call/caller/callee/bind使用方法与区别分析

    一.call 方法 调用一个对象的一个方法,以另一个对象替换当前对象(其实就是更改对象的内部指针,即改变对象的this指向的内容). Js代码 call([thisObj[,arg1[, arg2[, ...

  3. 2021年了,`IEnumerator`、`IEnumerable`还傻傻分不清楚?

    IEnumerator.IEnumerable这两个接口单词相近.含义相关,傻傻分不清楚. 入行多年,一直没有系统性梳理这对李逵李鬼. 最近本人在怼着why神的<其实吧,LRU也就那么回事> ...

  4. JS魔法堂:属性、特性,傻傻分不清楚

    一.前言 或许你和我一样都曾经被下面的代码所困扰 var el = document.getElementById('dummy'); el.hello = "test"; con ...

  5. javascript中bind,apply,call的相同和不同之处

    javasctipt中bind,apply,call的相同点是: 1,都是用来改变this的指向; 2,都可以通过后续参数进行传参; 3,第一个参数都是指定this要指向的对象; 不同点: 1,调用方 ...

  6. .bind.apply() 解决 new 操作符不能用与 apply 或 call 同时使用

    背景: 小明想要用数组的形式为 Cls.func 传入多个参数,他想到了以下的写法: var a = new Cls.func.apply(null, [1, 2, 3]); 然而浏览器却报错Cls. ...

  7. Java:接口和抽象类,傻傻分不清楚?

    01. 来看网络上对接口的一番解释: 接口(英文:Interface),在 Java 编程语言中是一个抽象类型,是抽象方法的集合.一个类通过继承接口的方式,从而来继承接口的抽象方法. 兄弟们,你们怎么 ...

  8. [转帖]十分钟快速理解DPI和PPI,不再傻傻分不清!

    十分钟快速理解DPI和PPI,不再傻傻分不清! https://baijiahao.baidu.com/s?id=1605834796518990333&wfr=spider&for= ...

  9. bind,apply,call的区别

    在Javascript中,bind, apply, call方法都可以显式绑定上下文this,这三者有何不同呢? bind只绑定this不马上执行 var person = { firstname: ...

  10. 【华为敏捷/DevOps实践】7. 敏捷,DevOps,傻傻不分清楚【华为云技术分享】

    文:姚冬(华为云DevCloud首席技术布道师,资深DevOps与精益/敏捷专家,金融解决方案技术Leader,中国DevOpsDays社区核心组织者) 前言 敏捷是什么?DevOps是什么?两者有什 ...

随机推荐

  1. mysql分页查询按某类型置顶 按某类型置尾 再按优先级排序

    近段时间接到一个新需求: 第一优先级:未满的标的顺位高于已满标的顺位.第二优先级:新手标的顺位高于其他标的的顺位. 第三优先级:标的剩余可投金额少的顺位高于标的剩余可投金额多的. 我是直接通过sql语 ...

  2. poj2186(tarjan缩点)

    题意:有n头奶牛,假如奶牛A觉得奶牛B很厉害,那么就有一条由A指向B的边,然后有个传递关系,if(A→B,B→C,那么A→C),让你求出被除了自己以外所有的奶牛都认为厉害的的奶牛个数: 解题思路:看到 ...

  3. 实验吧 WEB 貌似有点难

    错误!你的IP不在允许列表之内! 提示:代码审计 这个提示可谓是非常良心了,一看源代码是一个识别ip地址的东西,如果IP为1.1.1.1那么就会得到KEY. 第一个if是判断是否有client-ip ...

  4. Android Dialog 简单封装

    转载:https://www.cnblogs.com/zjjne/archive/2013/10/03/3350382.html public class MyAlertDialog { //regi ...

  5. UOJ370 滑稽树上滑稽果 【状压DP】

    题目分析: 答案肯定是链,否则可以把枝干放到主干. 去除一直存在的位,这样0位占满时就会结束. 用$f[S]$表示0位填埋情况,每次转移是它的一个子集,我们考虑可否转移. 再用$g[S]$存储转移是否 ...

  6. Python_sys.argv 命令行参数获取使用方法

    import sys print(sys.argv) """ 获取命令行参数 输入 python3 sys.argv_demo.py 输出: ['argv.py'] 输入 ...

  7. FlatList

    FlatList 之前使用的组件是ListView,当时要添加一个下拉刷新,上拉加载的功能,所以对ListView做了一些封装,但是后来看官方文档,不建议再使用ListView,因为效率问题,做过An ...

  8. 【BZOJ5213】[ZJOI2018]迷宫(神仙题)

    [BZOJ5213][ZJOI2018]迷宫(神仙题) 题面 BZOJ 洛谷 题解 首先可以很容易的得到一个\(K\)个点的答案. 构建\(K\)个点分别表示\(mod\ K\)的余数.那么点\(i\ ...

  9. JS基本类型-引用类型-深浅拷贝

    在JavaScript中变量包含两种类型的值:一种是基本类型,一种是引用类型. 基本类型包括:数值.字符串.null.undefined.布尔值引用类型包括:对象.数组.函数.正则… 补充: null ...

  10. cf366C Dima and Salad (dp)

    是一个01分数规划的形式,只不过已经帮你二分好了. 把b乘过去,再减回来,找和等于0的a的最大值就行了 #include<bits/stdc++.h> #define pa pair< ...