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

JavaScirpt之apply&call和bind #2

Open
heyushuo opened this issue Dec 27, 2019 · 0 comments
Open

JavaScirpt之apply&call和bind #2

heyushuo opened this issue Dec 27, 2019 · 0 comments

Comments

@heyushuo
Copy link
Owner

一.call()和 apply()概念和区别

1.概念

在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向。

2.区别

call()和 apply()唯一区别在于传参数,apply()接收两个参数,一个是在其运行函数中的作用域,另外一个是参数数组其中,第二参数可以是 Array 的实例,也可以是 arguments 对象,call()第一个参数和 apply()一样,第二个参数必须逐个列举出来,通过代码展示

function sum(num1, num2) {
  return num1 + num2;
}

function applySum(num1, num2) {
  console.log(arguments);
  //此时this对象是全局window对象
  return sum.apply(this, arguments);
  // 或者
  return sum.apply(this, [num1, num2]);
}
console.log(applySum(1, 2));
/**
call()和apply()发放唯一区别在于传参数.call()传参数必须逐个列举出来
*/
function callSum(num1, num2) {
  console.log(...arguments);
  //此时this对象是全局window对象
  return sum.call(this, num1, num2);
  // 或者使用ES6的语法
  return sum.call(this, ...arguments);
}
console.log(callSum(1, 2));

3.传递参数并非 apply 和 call 的真正的用武之地,他们真正强大的地方是能够扩充函数赖以运行的作用域

var o = {
  name: "kebi"
};
window.name = "heyushuo";

function sayName() {
  console.log(this.name);
}
sayName.call(this); //heyushuo
sayName.call(window); //heyushuo
sayName.call(o); //kebi  此时函数的执行环境不一样了,因为此时函数体内的this对象指向了o,于是结果显示的是'kebi'
//call和apply来扩充作用域的最大好处就是对象不需要与方法有任何耦合关系,

4.apply 和 call 的一些骚操作

//1.数组合并
var arr1 = [1, 2, 3];
var arr2 = ["heyushuo", "kebi"];
//arr1改变数组的作用域,arr2传的参数
Array.prototype.push.apply(arr1, arr2); //[1,2,3,'heyushuo','kebi']
//或者
arr1.concat(arr2)
// 或者ES6的语法
[...arr1, ...arr2];

//2.数组中的最大值
Math.max.apply(Math,arr1);
//或者es6的语法
Math.max(...arr1);

//3.判断对象的数据类型
//在最原始的对象中进行,不能直接arr1.toString()  或者 o.tosString() 因为对象和数组已经把原始对象的toString()方法进行了修改
Object.prototype.toString.call(arr1); // [object Array]
Object.prototype.toString.call(o)); //[object Object]

//4.可以把伪数组变成真正的数组,例如 arguments / document.getElementsByTagName("span")
Array.prototype.slice.call(document.getElementsByTagName("span"), 0))
//或者使用es6的语法
[...document.getElementsByTagName("span")]

二.bind()方法,ES5 提供了另外一个方法

解释: bind()和 call,apply 的作用是一样的,bind()这个方法会创建一个函数的实例,该方法可传入两个参数,第一个参数作为 this,第二个及以后的参数则作为函数的参数调用,这个方法和 call,apply 最重要的区别是,绑定 bind()后会创建一个新的函数,并且不会自动执行,需要调用执行

//通过这个例子看一下三者的区别
var o = {
  name: "kebi"
};
window.name = "heyushuo";

function sayName() {
  console.log(this.name);
}

sayName.call(window); //heyushuo
sayName.call(o); //kebi
sayName.apply(window); //heyushuo
sayName.apply(o); //kebi
//这是bind的用法
var objName = sayName.bind(o); //ie9+
objName(); //kebi

三.总结

  • apply,call,bind 三者都是用来改变函数的 this 对象的指向的;
  • apply,call,bind 三者都可以利用后续参数传参;
  • bind 是返回对应函数,便于稍后调用;apply,call 则是立即调用;
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