1. 判断对象数据类型
初始代码:
const isType = function (type) {
return function (t) {
return `[object ${type}]` === Object.prototype.toString.call(t)
}
}
const isArray = isType('Array')
console.log(isArray([]))
简化后:
const isType = type => t => `[object ${type}]` === Object.prototype.toString.call(t)
const isArray = isType('Array')
// 此时 isArray 为
// isArray = t => `[object Array]` === Object.prototype.toString.call(t)
原理:
Object 的原型上有 toString 方法,可以返回对象的数据类型;
例:传入 [1, 2, 3]
调用后得 [object Array] 字符串;传入 { name: ‘aaa’ }
调用后得 [object Object] 字符串。
注意:
- 为什么要用
call()
?
首先要解释原型链,当对象实例调用方法时,如果找不到该方法的声明,会按照原型链一次向上找,直到找到最近的一个声明。如果直接使用数组实例(以数组为例):[1, 2, 3].prototype.toString 或 [1, 2, 3].toString
,此时会根据原型链向上寻找,然而在Object
对象上也有一个toString
方法(强制类型转换为字符),此时会优先执行这个方法,所以不会达到目的,所以需要跳过原型链直接去执行Object
原型上的toString
。
call()
方法的作用是执行一个方法,并改变这个方法的 this 指向,所以利用Object.prototype.toString.call(t)
强制执行Object.prototype.toString
并且把 this 指向 参数t
。 isType(‘Array’)
在传入参数时,首字母必须大写
扩展:
call()
、apply()
、bind()
方法都可以改变原方法的 this 指向;call()
方法参数是 (this
指向, 原方法所需参数1, 原方法所需参数2 ) ,会直接调用函数;apply()
方法参数是 (this
指向, [ 原方法所需参数1, 原方法所需参数2 ]) ,会直接调用函数;bind()
方法参数是 (this
指向, 原方法所需参数1, 原方法所需参数2 ) ,会返回一个新函数。
2. 利用原生JS实现map方法
-
什么是
map()
方法?
数组调用map()
方法后会返回一个满足条件的新数组.第一个参数是需要循环执行的回调函数(必须),第二个参数是回调函数中的this
指向。- 回调函数有三个参数:item,index,arr
- item:当前数组项,
- index:当前数组索引,
- arr:当前数组
- 当第二个参数为空、传入
null
或undefined
时,会默认指向window
注意:当使用 ES6 箭头函数时,第二个参数会因为箭头函数的词法绑定而失效
例:
const arr = [1, 2, 3, 4]
window.number = 1
let obj = {number: 2}
// 第二个参数不传
let arr1 = arr.map(function (item, index, arr) {
// return item * number // 此时 number 为 window.number
return item * this.number // 此时 number 也为 window.number
})
console.log(arr1) // [1, 2, 3, 4]
// 第二个参数传入obj
let arr2 = arr.map(function (item, index, arr) {
// return item * number // 此时 number 为 window.number,可知不使用this不会改变指向
return item * this.number // 此时 number 变为 obj.number
}, obj)
console.log(arr2) // [2, 4, 6, 8]
// 使用箭头函数
let arr3 = arr.map((item, index, arr) => {
return item * this.number // 此时 number 为 window.number,第二个参数失效
}, obj)
console.log(arr3) // [1, 2, 3, 4]
- 利用原生JS实现
map()
Array.prototype.myMap = function (fn, pointer) {
let newArr = []
for (let i = 0; i < this.length; i++) {
newArr.push(fn.call(pointer, this[i], i, this))
}
return newArr
}
3. 利用原生JS实现filter方法
-
什么是
filter()
方法?
数组的filter()
方法是过滤器,对数组中的每一项通过回调函数进行筛选,返回一个每项都满足条件的新数组。第一个参数是需要循环执行的回调函数(必须),第二个参数是回调函数中的this
指向。- 回调函数有三个参数:item,index,arr
- item:当前数组项,
- index:当前数组索引,
- arr:当前数组
- 当第二个参数为空、传入
null
或undefined
时,会默认指向window
注意:
- 当使用 ES6 箭头函数时,第二个参数会因为箭头函数的词法绑定而失效
filter()
方法不会检测空数组filter()
方法不会改变原数组
-
利用原生JS实现
filter()
Array.prototype.myFilter = function (fn, pointer) {
let newArr = []
for (let i = 0; i < this.length; i++) {
fn.call(pointer, this[i], i, this) ? newArr.push(this[i]) : false
// fn.call(pointer, this[i], i, this) ? newArr.push(this[i]) : continue
// continue 处报错,三元表达式内不能使用语句
}
return newArr
}
4. 利用原生JS实现some方法
-
什么是
some()
方法?
数组的some()
方法对数组中的每一项通过回调函数进行筛选,返回一个Boolean
类型值,当有一个值都满足条件,返回true
,剩余值不检测,否则返回false
。第一个参数是需要循环执行的回调函数(必须),第二个参数是回调函数中的 this 指向。- 回调函数有三个参数:item,index,arr
- item:当前数组项,
- index:当前数组索引,
- arr:当前数组
- 当第二个参数为空、传入
null
或undefined
时,会默认指向window
注意:
- 当使用 ES6 箭头函数时,第二个参数会因为箭头函数的词法绑定而失效
- 当数组为空时,返回
false
-
利用原生JS实现
some()
Array.prototype.mySome = function (fn, pointer) {
let isTrue = false
for (let i = 0; i < this.length; i++) {
if (fn.call(pointer, this[i], i, this)) {
isTrue = true
break
}
}
return isTrue
}
问题参考链接:
(本文会持续更新)
以上是本人对于上述链接中提到的某些问题的个人理解,仅供参考,如有错误,还望大神指正。