面试高频——常考JS对象方法原理浅析实现
文章目录
1、call 方法
call()
方法使用一个指定的this
值和单独给出的一个或多个参数来调用一个函数。备注:该方法的语法和作用与
apply()
方法类似,只有一个区别,就是call()
方法接受的是一个参数列表,而apply()
方法接受的是一个包含多个参数的数组。
Function.prototype.myCall = function(context,...args){
// 参考call的做法,若context不存在则为winodw
context = context || window
//context 为传来的上下文,即要作为this的obj对象
// this 此时为对应的方法
// 此刻要做的就是模拟一个原方法,并将该方法的this改为context
const fn = Symbol() // 先创建一个symbol类型的防止命名重叠
context[fn] = this // 模拟原方法
context[fn](...args)
}
2、apply方法
apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。
// 代码实现
Function.prototype.myApply = function(context,args){
context = context || window
const fn = Symbol()
context[fn] = this
context[fn](...args)
}
3、new 关键字实现
new
运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
new
关键字会进行如下的操作:
- 创建一个空的简单JavaScript对象(即
{}
);- 为步骤1新创建的对象添加属性
__proto__
,将该属性链接至构造函数的原型对象 ;- 将步骤1新创建的对象作为
this
的上下文 ;- 如果该函数没有返回对象,则返回
this
。
function MyNew(fn,...args){
// 创建一个空对象
const obj = {}
// 将新对象的__proto__指向它构造函数的原型
Object.setPrototypeOf(obj,fn.prototype)
// 调用构造函数,传参数初始化,并将this改为obj
const result = fn.apply(obj,args)
// 判断构造函数有没有返回值,1.返回的是基础类型,则返回实例对象,2.返回函数则返回函数,3,返回对象则返回它指定的对象
return result instanceof Object? result:obj
}
function Person(name,age){
this.name = name
this.age = age
return 22 // 实例对象
// return function(){} // 函数
// return {} // 指定对象
}
对象方法
1、entries
Object.entries()
方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用for...in
循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)。
// entries
Object.prototype.myEntries = function(obj){
let res = []
for(let key in obj){
obj.hasOwnProperty(key) && res.push([key,obj[key]]) // hasOwnProperty 过略掉原型上的属性
}
return res
}
2、fromEntries
Object.fromEntries()
方法把键值对列表转换为一个对象。
//fromEntries
Object.prototype.myFromEntres = function(Arr){
let obj = {}
for(let [key,value] of Arr){
obj[key] = value
}
return obj
}
3、keys
Object.keys()
方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致 。
// keys
Object.prototype.myKeys = function(obj){
let res = []
for(let key in obj){
obj.hasOwnProperty(key) && res.push(key)
}
return res
}
4、values
Object.values()
方法返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用for...in
循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。
Object.prototype.myValues = function(obj){
let res = []
for(let key in obj){
obj.hasOwnProperty(key) && res.push(obj[key])
}
return res
}
5、instanceOf
用处:A instanceOf B,判断A是否经过B的原型链
function MyInstanceOf(son,father){
// 目标对象的原型对象
let fp = father?.prototype
// 自身的原型链
let sp = son?.__proto__
// 判断自身的原型是否在目标对象的原型链上
while(sp){
if(sp == fp){
return true
}
// 向上找原型
sp = sp.__proto__
}
// 不在原型链上返回false
return false
}
6、is
用处:Object.is(a, b),判断a是否等于b
Object.prototype.sx_is = function (x, y) {
if (x === y) {
// 防止 -0 和 +0
return x !== 0 || 1 / x === 1 / y
}
// 防止NaN
return x !== x && y !== y
}