08-12 call-apply的总结
- call,apply作用:改变this指向
- 两者区别就是传参:call传参数直接写,apply传参要用数组包起来
- call,apply应用场景:
js继承:子构造函数通过调用父构造函数的 call
方法来实现继承
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
function Toy(name, price) {
Product.call(this, name, price);
this.category = 'toy';
}
var cheese = new Food('feta', 5);
var fun = new Toy('robot', 40);
判断复杂数据类型对象/数组(typeof 对{ },[ ]都是返回结果Obejct)
//typeof [] //object
//typeof {} //object
console.log(Object.prototype.toString.call({}) === '[object Object]') //[object Object]
console.log(Object.prototype.toString.call([]) === '[object Array]') //[object Array]
es5 把伪数组转换成数组
//伪数组转数组
function get() {
console.log(arguments)
console.log([...arguments])
console.log(Array.prototype.slice.call(arguments))
console.log(Array.from(arguments))
}
get(1,2,3)
- 手写call方法
// call作用 改变this指向
let person = {
getName:function () {
return this.name
}
}
//实现手写call
// function myCall(obj) {
// 直接声明是不行的,getName这个函数对象里找不到这个属性
// }
//解决:对函数对象的原型链添加新的属性myCall
//参数接受的是改变this指向的参数
Function.prototype.myCall = function (context) {
//这里面的this是谁?(getName进行调用,因此正常情况下是getName自身,也就是function)
//这里的this必须是一个function
console.log(typeof this)//function
if (typeof this !== 'function'){
throw new Error('error')
}
console.log(...arguments)//这里是获取了全部的参数
//按照call里的参数获取,我们需要拿到除了第一个参数之外的参数
let args = [...arguments].slice(1)
context = {...context} || window//避免对象浅复制的问题
//在传入的对象里,假设有一个方法
context.tmp = this //显式改变指向
return context.tmp(...args)
}
let p = {
name:'sikara'
}
console.log(person.getName.call(p))
console.log(person.getName.myCall(p,1,2,3))
console.log(p)
- 手写apply
//手写apply
Function.prototype.myApply = function (context) {
//这里面的this是谁?(getName进行调用,因此正常情况下是getName自身,也就是function)
//这里的this必须是一个function
if (typeof this !== 'function'){
throw new Error('error')
}
console.log(...arguments)//这里是获取了全部的参数
let res
//在传入的对象里,假设有一个方法
context.tmp = this //显式改变指向
if (arguments[1]){
res = context.tmp(...arguments[1])
}else {
res = context.tmp()
}
delete context.tmp //删除对象属性,保证代码严谨
return res
}