call和apply唯一的区别是传参的形式不同,bind与他们之前的区别是bind不是立即执行,它返回一个绑定了上下文的函数。
ps,call在非严格模式下,如果不传参数,或者第一个参数是null或nudefined,this都指向window;
let fn = function(a,b){
console.log(this,a,b);
}
let obj = {name:"obj"};
fn.call(obj,1,2); // this:obj a:1 b:2
fn.call(1,2); // this:1 a:2 b:undefined
fn.call(); // this:window a:undefined b:undefined
fn.call(null); // this=window a=undefined b=undefined
fn.call(undefined); // this=window a=undefined b=undefined
————————————————
在严格模式下,第一个参数是谁,this就指向谁,包括null和undefined,如果不传参数this就是undefined。
"use strict"
let fn = function(a,b){
console.log(this,a,b);
}
let obj = {name:"obj"};
fn.call(obj,1,2); // this:obj a:1 b:2
fn.call(1,2); // this:1 a:2 b=undefined
fn.call(); // this:undefined a:undefined b:undefined
fn.call(null); // this:null a:undefined b:undefined
fn.call(undefined); // this:undefined a:undefined b:undefined
————————————————
下面总结了call和apply的一些常用的地方。
1.将类数组转化为数组:
// arguments
// 返回值为数组,arguments保持不变
var arg=[].slice.call(arguments);
// nodeList
var nList=[].slice.call(document.getElementsByTagName('li'));
2.方法借用,改变this的值
var foo={
name:'joker',
showName:function(){
console.log(this.name);
}
};
var bar={name:'rose'};
foo.showName.call(bar);// rose
3.在继承中应用
// parent
var Person=function(name){
this.name=name;
this.gender=['man','woman'];
}
// child
var Student=function(name,age){
// inherit
Person.call(this);
}
Student.prototype.message=function(){
console.log('name:'+this.name+', age:'+this.age+', gender:.'+this.gender[0]);
}
var xm=newStudent('xiaom',12);
xm.message();//name:undefined, age:undefined, gender:.man
4.判断数据的类型
let arrayType = Object.prototype.toString.apply([])
let objType = Object.prototype.toString.apply({})
let stringType = Object.prototype.toString.apply("wwwww")
let numberType = Object.prototype.toString.apply(1111)
let nullType = Object.prototype.toString.apply(null)
let undefinedType = Object.prototype.toString.apply(c)
console.log(arrayType,objType,stringType,numberType,nullType,undefinedType)