Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

apply、call、bind的比较 #6

Open
CoolRabbit520 opened this issue Mar 13, 2018 · 0 comments
Open

apply、call、bind的比较 #6

CoolRabbit520 opened this issue Mar 13, 2018 · 0 comments

Comments

@CoolRabbit520
Copy link
Owner

CoolRabbit520 commented Mar 13, 2018

apply

函数对象具有apply方法,用于在特定作用域中调用函数,接受两个参数,this作用域和参数(arguments或[ , , ]形式的数组)。

call

函数对象具有call方法,用于在特定作用域中调用函数,接受两个参数,this作用域和参数(准确地传入每一个参数,必须逐个列举出来)。

bind

函数对象具有bind方法,用于创建一个新的绑定函数,该函数的this值会被绑定到bind()的参数,接受一个参数,this作用域。

var bar = function(){
console.log(this.x);
}
var foo = {
x:3
}
bar(); // undefined
var func = bar.bind(foo);
func(); // 3

apply、call、bind比较

当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会立即执行函数。

var obj = {
    x: 81,
};
 
var foo = {
    getX: function() {
        return this.x;
    }
}
 
console.log(foo.getX.bind(obj)());  //81
console.log(foo.getX.call(obj));    //81
console.log(foo.getX.apply(obj));   //81

总结:
apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;
apply 、 call 、bind 三者都可以利用后续参数传参;
bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用

call和apply和比较

call和apply的作用相同,他们的区别在于接收参数的方式不同

进阶

  1. 他们正在强大的地方在于扩充函数赖以生存的作用域。

  2. 最大的好处是:对象不需要与方法有任何关系,就能指定作用域。之前在指定的作用域中调用函数,需要将该函数放到对象中,再通过对象来调用该函数。
    call和apply是为了动态改变this。函数的this不在调用时改变的话,就是全局变量;对象的this就是自身。call和apply可以动态地改变this的值。
    当一个object没有某个方法,但是其他的有,我们可以借助call或apply用其它对象的方法来操作。

function fruits() {}
 
fruits.prototype = {
    color: "red",
    say: function() {
        console.log("My color is " + this.color);
    }
}
 
var apple = new fruits;
apple.say();    //My color is red

banana = {
    color: "yellow"
}
apple.say.call(banana);     //My color is yellow
apple.say.apply(banana);    //My color is yellow
  1. 借用JavaScript中的原生引用类型中内置的方法。比如Array、Math、String。

例一:

var  numbers = [5, 458 , 120 , -215 ]; 
var maxInNumbers = Math.max.apply(Math, numbers),   //458
var maxInNumbers2 = Math.max(5, 458 , 120 , -215),   //458

number 本身没有 max 方法,但是 Math 有,我们就可以借助apply 使用其方法。
实际上这里是借助apply方法,就可以直接将数组传入,而不用手动地将数组中的项一个一个写入。

Math是javascript中的单体内置对象。Math对象包含数学计算中的一些特殊值;还包含一些简繁或者复杂的计算方法

例二:

var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"));

Javascript中存在一种名为伪数组的对象结构。比较特别的是 arguments 对象,还有像调用 getElementsByTagName , document.childNodes 之类的,它们返回NodeList对象都属于伪数组。不能应用 Array下的 push , pop 等方法。
通过 Array.prototype.slice.call 转化为标准数组,再使用数组方法。
但是我们能通过 Array.prototype.slice.call 转换为真正的数组的带有 length 属性的对象,这样 domNodes 就可以应用 Array 下的所有方法了。
例三:

var array1 = [12 , "foo" , {name "Joe"} , -2458]; 
var array2 = ["Doe" , 555 , 100]; 
Array.prototype.push.apply(array1, array2); 
/* array1 值为  [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 555 , 100] */

例四:

function log(){
  console.log.apply(console, arguments);
};
log(1);    //1
log(1,2);    //1 2
  1. apply有一个特点,就是可以传入一个数组作为参数,这样对于数组操作很方便。
var array1 = [12 , "foo" , {name "Joe"} , -2458]; 
var array2 = ["Doe" , 555 , 100]; 
Array.prototype.push.apply(array1, array2); 

这样就不用将array2转换为一个个参数依次传入。

补充

JavaScript 的一大特点是,函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以改变的」这样的概念。

参考资料

1.【优雅代码】深入浅出 妙用Javascript中apply、call、bind - ChokCoco - 博客园
2. (1 封私信 / 10 条消息)如何理解和熟练运用js中的call及apply? - 知乎

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant