作用:首先这三个函数的存在意义是什么?答案是改变函数执行时的上下文,再具体一点就是改变函数运行时的this指向;
call、apply与bind的区别:call和apply改变了函数的this上下文后便执行该函数,而bind则是返回改变了上下文后的一个函数。
bind()方法创建一个新的函数(称为绑定函数), 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。
语法:
fun.bind(thisArg[, arg1[, arg2[, ...]]])
参数thisArg表示:当绑定函数被调用时,该参数会作为this的指向。当使用new
操作符调用绑定函数时,该参数无效。
参数arg1, arg2, ...表示:
当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。
拿一个实例更好的理解bind的指向问题
this.name="jack"; var demo={ name:"rose", getName:function(){return this.name;} } console.log(demo.getName());//输出rose 这里的this指向demo var another=demo.getName; console.log(another())//输出jack 这里的this指向全局对象 //运用bind方法更改this指向 var another2=another.bind(demo); console.log(another2());//输出rose 这里this指向了demo对象了
bind的应用
可以对一个函数预设初始参数:
function a(){ return Array.prototype.slice.call(arguments);//将类数组转换成真正的数组 } var b=a.bind(this,15,20) alert(b());//弹出 15,20 var s=b(25,30); alert(s);//弹出 15,20,25,30
call、apply的区别
他们俩之间的差别在于参数的区别,call和aplly的第一个参数都是要改变上下文的对象,call()和apply()方法都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。apply和call方法的第一个参数都是特定的作用域第二个参数不同。
而call从第二个参数开始以参数列表的形式展现,需要逐个列出需要传递的参数。
apply则是把除了改变上下文对象的参数放在一个数组里面作为它的第二个参数。可以是Array的实例,也可以是arguments对象。
fn.call(obj, arg1, arg2, arg3...); fn.apply(obj, [arg1, arg2, arg3...]);
例子:
将伪数组转化为数组
js中的伪数组(例如通过document.getElementsByTagName
获取的元素)具有length属性,并且可以通过0、1、2…下标来访问其中的元素,但是没有Array中的push、pop等方法。我们可以利用call、apply来将其转化为真正的数组这样便可以方便地使用数组方法了。
var arrayLike = { 0: 'qianlong', 1: 'ziqi', 2: 'qianduan', length: 3 }
上面就是一个普通的对象字面量,怎么把它变成一个数组呢?最简单的方法就是
var arr = Array.prototype.slice.call(arrayLike);
console.log(arr) //["qianlong", "ziqi", "qianduan"]
Array.prototype.slice.call()可以理解为:改变数组的slice方法的作用域,在特定作用域中去调用slice方法,call()方法的第二个参数表示传递给slice的参数即截取数组的起始位置。
没有length属性的对象
var obj = {0:'hello',1:'world'};//没有length属性 console.log(Array.prototype.slice.call(obj,0));//[]
数组追加
在js中要往数组中添加元素,可以直接用push方法,
var arr1 = [1,2,3]; var arr2 = [4,5,6]; [].push.apply(arr1, arr2); // arr1 [1, 2, 3, 4, 5, 6] // arr2 [4,5,6]
判断变量类型
对于对象型的数据类型,我们可以借助call来得知他的具体类型,例如数组
function isArray(obj){ return Object.prototype.toString.call(obj) == '[object Array]'; } isArray([]) // true
判断基本类型
Object.prototype.toString.call(null); // "[object Null]" Object.prototype.toString.call(undefined); // "[object Undefined]" Object.prototype.toString.call(“abc”);// "[object String]" Object.prototype.toString.call(123);// "[object Number]" Object.prototype.toString.call(true);// "[object Boolean]"
利用call和apply做继承
var Person = function (name, age) { this.name = name; this.age = age; }; var Girl = function (name,age) { Person.call(this, name,age); }; var Boy = function (name, age) { Person.apply(this, arguments); } var g1 = new Girl ('qing',100); var b1 = new Boy('qianlong', 100) console.log(g1);//Girl {name: "qing", age: 100} console.log(b1);//Boy {name: "qianlong", age: 100}