JavaScript1 分钟阅读

JavaScript 方法重写

构造函数上是否有Symbol.hasInstanceSymbol.hasInstance用于判断某对象是否为某构造器的实例。因此你可以用它自定义 instanceof 操作符在某个…

李李顺2024 · 05 · 24

数组

reduce
js
// reduce 用来迭代数组的方法,实现累计
// arr.reduce(callback, initial),依次迭代数组中的每一项,并且每次把callback执行,传递三个值
//  result: 上一次迭代的结果,并作为初始值传递给下一次迭代[如果是第一次执行,默认是数组的第一项]
//  item:依次遍历的每一项
//  index:数组下标
Array.prototype.reduce = function(callback, initial) {
	if (typeof callback !== 'function') throw new Error('callback must be a function')
  let self = this
  let i = 0
  let len = self.length
  if (typeof initial === 'undefined') {
  	initial = self[0]
    i = 1
  }
  for(; i < len; i++) {
  	let item = self[i]
    initial = callback(initial, item, i)
  }
  return initial
}
reduceRight
js
// 反向迭代数组
Array.prototype.reduceRight = function (callback, initial) {
	if (typeof callback !== 'function') throw new TypeError('callback is must be a function!')
  let self = this,
      len = self.length,
      i = len - 1
  if (typeof initial === 'undefined') {
    initial = self[len - 1]
  	i = len - 2
  }
  for(; i > 0; i--) {
  	let item = self[i]
    initial = callback(initial, item, i)
  }
  return initial
}
map
js
// 同forEach,只是map方法有返回值
Array.prototype.map = function map(callback, initial) {
    if (typeof callback !== 'function') throw new TypeError('callback must be a function')
    let self = this
    let i = 0
    let len = self.length
    let ary = []
    initial = initial || self
    for (; i < len; i++) {
        let item = self[i]
        ary[i] = callback(item, i, initial)
    }
    return ary
}
filter
js
// 过滤数组中的每一项,返回符合条件的项
Array.prototype.filter = function filter(callback, initial) {
    if (typeof callback !== 'function') throw new TypeError('callback must be a function')
    let self = this
    let i = 0
    let len = self.length
    let ary = []
    initial = initial || self
    for (; i < len; i++) {
        let item = self[i]
        if (callback(item, i, initial)) ary.push(item)
    }
    return ary
}
some
js
// 判断数组中是否有符合条件的项
Array.prototype.some = function some(callback, initial) {
    if (typeof callback !== 'function') throw new TypeError('callback must be a function')
    let self = this
    let i = 0
    let len = self.length
    initial = initial || self
    for (; i < len; i++) {
        let item = self[i]
        if (callback(item, i, initial)) return true
    }
    return false
}

函数

call
js
Function.prototype.call = function call(context, ...params) {
  if (context == null) context = window
  let self = this
  context.fn = self
  let result = context.fn(...params)
  delete context.fn
  return result
}
apply
js
Function.prototype.apply = function apply(context, params) {
  if (context == null) context = window
  let self = this
  context.fn = self
  let result
  if (params) {
    result = context.fn(...params)
  } else {
    result = context.fn()
  }
  delete context.fn
  return result
}
bind
js
Function.prototype.bind = function bind (context) {
  if (context == null) context = window
  var params = [].slice.call(context, 1)
  var self = this
	return function proxy(){
  	var args = [].slice.call(arguments)
    params = params.concat(args)
    return self.apply(context, params)
  }
}
/* Function.prototype.bind = function bind(context, ...params) {
    if (context == null) context = window;
    let self = this;
    return function proxy(...args) {
        params = params.concat(args);
        return self.call(context, ...params);
    };
}; */

对象

for in

弊端

  • 优先遍历数字属性,并且按照从小到大遍历,然后再去遍历其他
  • 无法遍历Symbol私有属性
  • 遍历了所属类原型上自定义且未设置不可枚举属性(enumerable)的属性和方法[遍历了共有的,内置的是不可枚举的]
js
Object.prototype.xx = 'xx'
let obj = {
  name: 'test',
  age: 18,
  3: 3,
  0: 10,
  [Symbol('A')]: function(){}
}

for(let key in obj) console.log(key)

// 0, 3, name, age, xx

function forInSelf(obj, callback) {
  	// 获取私有的属性:Object.keys(obj) OR Object.getOwnPropertyNames(obj) ;返回包含所有非symbol私有属性的数组
    // Object.getOwnPropertySymbols 获取所有的Symbol私有属性「数组」
    let keys = [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)]
    let len = keys.length
    for(let i = 0; i < len; i++) {
        let key = keys[i]
        let value = obj[key]
        callback(value, key)
    }
}
forInSelf(obj, (value, key) => {
    console.log(key)
})
// 0, 3, name, age, Symbol(A)
检测是否是对象的公有属性
js
Oobject.prototype.hasPubProperty = function hasPubPtoperty(attr) {
  var self = this
	var prototype = Object.getPrototypeOf(self)
  while(prototype) {
    if (prototype.hasOwnProperty(attr)) return true
    /* var keys = Object.keys(prototype) 这样是获取不到内置类原型上的属性和方法的
    if (typeof Symbol !== 'undefined') {
    	keys.concat(Object.getOwnPropertySymbol(prototype))
    }
    if (keys.indexof(attr) >= 0) return true*/
  	prototype = Object.getPrototypeOf(prototype)
  }
  return false
}
instanceof

检测原理: 构造函数上是否有Symbol.hasInstance[Symbol.hasInstance用于判断某对象是否为某构造器的实例。因此你可以用它自定义 instanceof 操作符在某个类上的行为。] 检测构造函数的prototype是否出现在实例的__proto__上

js

function Instance_of (example, classFunc) {
  // 参数检查 
  if (typeof classFunc === 'undefined') throw new TypeError('params of classFunc is not a function')
  if (example == null) return false
  // 如果支持Symbol.hasInstance就用此方法来检测
  if (typeof Symbol !== 'undefined') {
    var hasInstance = classFunc[Symbol.hasInstance]
    if (typeof hasInstance !== 'undefined') {
      return hasInstance.call(classFunc, example)
    }
  }
  // 基于原型链的方式来检测
  var prototype = classFunc.prototype
  // 获取构造函数的原型对象[箭头函数没有prototype属性]
  var proto = Object.getPrototypeOf(example)
  // 获取对象的__proto__属性
  if (!prototype) return false
  while(true) {
    if (proto === null) return false
    if (proto === prototype) return true
    proto = Object.getPrototypeOf(proto)
  }
}
new

new 操作符的机制:

默认创建一个对象[实例],并且将这个实例对象的__proto__属性指向类的prototype 把构造函数执行,并且让函数中的this指向创建的实例对象 如果实例对象没有返回值或者返回的是原始类型的值,默认将实例对象返回,如果返回的是对象类型,那么以返回值为主

js
function _new(Ctor, ...params) {
  let obj = {},
      result,
      reg = /^(object|function)$/
  obj.__proto__ = Ctor.prototype
  result = Ctor.call(obj, params)
  if (reg.test(typeof result)) return result
  return obj
}
// 兼容写法
function _new1(Ctor) {
    var reg = /^(object|function)$/,
        obj,
        params,
        result
    if (!reg.test(typeof Ctor) || !reg.test(typeof Ctor.prototype)) throw new TypeError('Ctor must be a function')
    params = [].slice.call(arguments, 1)
    obj = Object.create(Ctor.prototype)
    result = Ctor.apply(obj, params)
    if (reg.test(typeof result)) return result
    return obj
}
Object.create
js
// Object的实例无法调用create方法,所以需要create是Object的一个工具方法
// 返回一个对象,并且对象的__proto__ 指向prototype
Object.create = function create(prototype) {
    if (!/^(object|function)$/i.test(typeof prototype)) throw new TypeError('Object prototype may only be an Object or null');
  // 1、考虑IE的__proto__的问题,不能使用__proto__,那么只能基于类的方式来实现
    //function proxy() {}
    //proxy.prototype = prototype;
    //return new proxy;
  // 2、不考虑__proto__的问题
  var obj = {}
  obj.__proto__ = prototype
  return obj
};

标签 · TAGS

评论 · COMMENTS

评论由 Giscus 承载 · 需要 GitHub 账号登录

站点不保存任何读者账号与凭证

未配置:在 lib/site.config.ts 填入 giscus 的 repo / repoId / category / categoryId