爱生活,爱编程,学习使我快乐
JavaScript中,call、apply和bind方法都是可以用来改变this指向进行上下文绑定的,它们之间既有相似之处也有不同之处。
call和apply都是对函数的直接调用(即:修改this指向后并立马执行),而bind方法返回一个(被修改了this指向)的新函数,函数不会被执行。
function fn () {
console.log(this.a)
}
// 因为这时fn中的this指的是window,window下没有a,所以是undefined
fn() // undefined
// call、apply方法修改函数的this指向后会立即执行,输出结果
let obj = {a: '1'}
fn.call(obj) // 1
fn.apply(obj) // 1
// 因为使用call、apply把fn中的this指向修改成了obj,所以this.a就是obj.a => 1
// bind方法修改函数的this指向后不会立即执行,只是返回一个新函数,要想执行需要加上()去调用。
var fn1 = fn.bind(obj) // 这时不会执行,只是返回一个新函数
// 返回的新函数加上()去调用执行,输出结果
fn1() // 1
2.1、call和apply都可以传参数。call后面的参数与fn方法中是一一对应的,而apply的第二个参数是一个数组,数组中的元素是和fn方法中一一对应的,这就是两者最大的区别。
function fn (age, job) {
console.log(this.name, age, job)
}
fn.call({name: 'yang'}, 26, 'IT') // yang 26 IT
fn.apply({name: 'wang'}, [24, 'worker']) // yang 24 worker
// call和apply都是会直接调用函数
// 第一个参数都是函数执行时的this
// call后面的参数与fn方法中是一一对应的
// apply的第二个参数是一个数组,数组中的元素是和fn方法中一一对应
apply的多种用法
function sum(num1, num2){
return num1 + num2;
}
function callSum1(num1, num2){
return sum.apply(this, arguments); // 传入arguments对象
}
function callSum2(num1, num2){
return sum.apply(this, [num1, num2]); // 传入数组
}
alert(callSum1(10,10)); //20
alert(callSum2(10,10)); //20
2.2、bind是ES5中的方法,可以像call一样传参,也可以在调用的时候再进行传参。
function fn (age, job) {
console.log(this.name, age, job)
}
// 可以像call一样传参,第一个是this指向的对象,后面依次是与fn方法中是一一对应的参数。
var fn1 = fn.bind({name: 'yang'}, 26, 'IT')
fn1() // yang 26 IT
// 也可先修改this指向,然后在调用新方法时传入参数
var fn1 = fn.bind({name: 'yang'})
fn1(26, 'IT') // yang 26 IT
function fn () {
console.log(this.a)
}
var fn1 = fn.bind({a: 1})
var fn2 = fn.bind({a: 2})
var fn3 = fn.bind({a: 3})
fn()
// 可以在原函数(fn)上多次用bind修改this指向,返回多个被修改了this指向的新函数,且不会影响原函数
fn1() // 1
fn2() // 2
fn3() // 3
// bind只会改变一次this指向
// fn1已经的this指定已经被修改为了{a: 1},所以再使用fn1调用bind方法修改this指定是无效的。
var fn4 = fn1.bind({a: 100})
fn4() // 1
function fn () {
console.log(this)
}
fn.call(1) // Number {1}
// 如果传入的不是对象,而是数值1,则会被隐式转换对象形式
1、使用Object.prototype.toString.call
判断数据类型
Object.prototype.toString.call('') ; // [object String]
Object.prototype.toString.call(1) ; // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(Symbol()); //[object Symbol]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]
Object.prototype.toString.call(document) ; // [object HTMLDocument]
Object.prototype.toString.call(window) ; //[object global] window 是全局对象 global 的引用