apply
语法:
func.apply(thisArg, [argsArray])
参数
- thisArg:调用
func
的this
值,如果处于非严格模式下,则指定为null
或undefined
时会自动替换为指向全局对象 - argsArray:调用
func
的传参(参数需要放到一个数组中)
核心概念(借用)
举个栗子
有一天你一时兴起想做个红烧肉,但万事具备只欠口锅,但是买一个又不太划算,可下一次做可能得到猴年马月。但此时你发现与你合租的小姐姐刚好有这么一口锅,于是你便借了过来做起了红烧肉。
这就是apply
的用法,thisArg
表示你自己,func
则表示那口锅,apply
表示借用。
方法优点:靠改变this指向,对代码进行复用。减少重复代码,节约内存。
上代码:
function cooking(food) {
console.log(`我做了一顿${food}`)
}
function my(...args) {
cooking.apply(this, args)
}
my('红烧肉') // 我做了一顿红烧肉
复制代码
从上面的例子中可以看到,my
中没有定义任何方法,但是通过apply
以后,my
便借用了cooking
的方法。
用法总结
- 用
array
将一个数组push
到另一个数组中
let arr1=[1,2,3]
let arr2=[4,5]
Array.prototype.push.apply(arr1,arr2)
console.log(arr1) // [1,2,3,4,5]
复制代码
如果直接使用arr1.push(arr2)
得到的结果将会是一个数组作为整体传入。得不到我们想要的效果。而直接使用concat
的话,它返回的是一个新的数组,而不会对arr1
进行修改。
- 求数组中最大值
let number=[1,2,4,56,6]
let max=Math.max.apply(null,number)
console.log(max)
复制代码
因为Math.max
接收的参数为离散数,直接传入数组无法的到想要的结果。这种调用方式相当于Math.max(1,2,4,56,6)
- 继承
function Person(name){
this.name=name
this.say=function(){
console.log('my name is ' + name)
}
}
function My(name,age){
Person.apply(this,[name])
this.age=age
this.getAge=function(){
console.log(age)
}
}
let my=new My('hkj',22)
console.log(my.name)
my.say()
console.log(my.age)
my.getAge()
复制代码
通过new
生成的实例会继承构造函数中的属性和方法,而My
中定义的只有age
及getAge
方法,并未定义name
及say
方法。但是生成的实例依然可以调用,这就是apply
的借用导致的。虽然My
未定义此方法但是借了个Person
里的name
属性和say
方法来用。换成术语就是,My
继承了Person
中this
绑定的属性和方法。
类似用法还有很多,就不在此赘述了。只需要牢记借用这个概念就能记住它的用法了。
call
语法:
function.call(thisArg, arg1, arg2, ...)
参数
thisArg
:调用func
的this
值,如果处于非严格模式下,则指定为null
或undefined
时会自动替换为指向全局对象argsArray
:调用func
的传参(参数需要一个一个传)
用法
跟apply
一样,就是传参不一样,apply
传的是数组,而call
需要离散化参数传入。用个小技巧记忆:apply
需要传array
(数组)。call
反向记忆就行了。
Object.prototype.toString
判断数据类型
类型判断一直是个比较棘手的问题,而Object的toString方法则是最完美的解决办法。默认情况下调用返回值为
[object Object]
。后面的Object
就是返回的类型
var toString = Object.prototype.toString;
toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]
复制代码
可以看出第二个值表示的就是正确返回类型。如果直接调用的话,有些对象重写了toString
方法将会得不到我们想要的效果。
比如:
let arr=[1]
let date=new Date()
let fun = function () {}
console.log(date.toString()) // Thu Dec 05 2019 16:46:51 GMT+0800 (中国标准时间)
console.log(arr.toString()) // 1
console.log(fun) // ƒ () {}
console.log(Object.prototype.toString.call(arr)) // [object Array]
console.log(Object.prototype.toString.call(date)) // [object Date]
console.log(Object.prototype.toString.call(fun)) // [object Function]
复制代码
这种调用方式会直接调用
Object
原生的toString
方法,避免了调用重写后方法导致结果不正确的问题。
bind
下次写
小结
作为js中最重要的知识点之一,因为其抽象的特性,开始学起来确实有些困难,大部分时候都是知其然不知其所以然。但是它们的用法是很多后面需要学习的知识点的基石。只有牢牢掌握了它们的用法以后的学习才会更轻松。如果对继承用法感兴趣的同学可以阅读我的下一篇文章:深入理解JS原型,原型链,继承及new的实现原理
写作不易,各位小哥哥小姐姐觉得我的博客对你有帮助的话,请给我点个赞哟!
首发地址:https://juejin.im/post/5de8a9716fb9a016391d38a4
来源:掘金