你们都知道在函数中,最回味无穷的就是prototype属性了,对于ECMAScript中的引用类型而言,prototype是保存它们实力方法的真正所在。数组
诸如toString()和valueOf()等方法都保存在prototype名下,只不过是经过各自对象的实例访问。在建立自定义引用类型以及实现继承时,prototype属性的做用是极为重要的。app
每一个函数都包含两个非继承而来的方法:apply()和call(),它们都是在特定的做用域中调用函数,实际上就是设置函数体内this对象的值。函数
1.apply()this
apply()接收两个参数,第一个是在其中运行函数的做用域,另外一个是参数数组。其中第二个参数能够是Array的实例,也能够是arguments对象;spa
1 function sum(num1, num2) { 2 return num1 + num2; 3 } 4 function callSum1(num1, num2) { 5 return sum.apply(this, arguments); // 传入arguments对象 6 } 7 function callSum2(num1, num2) { 8 return sum.apply(this, [num1, num2]); // 传入数组 9 } 10 console.log(callSum1(10, 10)); // 20 11 console.log(callSum2(10, 10)); // 20
解释:上述代码callSum1()在执行sum()函数的时候传入了this做为this值(由于是在全局做用域中调用的,因此这个this就是window对象),以及第二个参数arguments;prototype
而callSum2()也调用了sum()函数,可是传入的是this和一个数组;他们的执行结果是相同的;code
⚠️上述代码执行是在非严格模式下,如果严格模式下this的值会是undefined;对象
2.call()blog
call()与apply()做用相同,区别仅在于接收参数的方式不一样,call()的第一个参数也是this,可是从第二个参数就要逐个的进行列举了;继承
function callSum3(num1, num2) { return sum.call(this, num1, num2); } console.log(callSum3(10, 10)); // 20
总结一下call()和apply(),它们的真正用武之地是----扩充函数运行的做用域
举个🌰:
window.color = "red"; var o = { color: 'blue' } function sayColor() { console.log(this.color); } sayColor(); // red sayColor.call(this); // red sayColor.apply(window); // red sayColor.call(o); // blue 解释:这里的this变成了对象o,而不是window
3.bind()
该方法会建立一个函数的实例,其this值会被绑定到传给bind()函数的值,例如
// 建立了两个函数实例,它们都须要手动的去执行一下 var exFunc = sayColor.bind(o); var exFunc1 = sayColor.bind(this); exFunc(); // blue exFunc1(); // red
最后:call()和apply()都会当即执行,而bind()会先建立一个函数实例,而后手动的去执行;它们都会继承传递给它们的函数的属性和方法哈哈哈。