【2020面试精选】 手写JavaScript常见API

8,243 阅读4分钟

【2020面试精选】 手写JavaScript常见API

一 请用ES5实现const功能

分析:

const与其他定义变量的方式不同点在于,const定义的基本类型,其值不可更改,const定义的引用类型,指向堆内存的地址不能更改(注意:此处说的是内存地址不变,而不是内存地址指向的内存空间里所存储的数据不变)

思路:

要想实现变量的值不被重写,如果我们能监听到变量赋值操作,我们就可以阻止变量赋值,进而就可以实现赋值拦截。问题转化成监听赋值操作,首先想到的便是Object.defineProperty()方法,它可以定义对象属性的基础属性,包括取值赋值。但是这里有一个问题:这个方法是针对对象的,那全局变量怎么办?这里要注意的是:全局变量实际上是全局对象window的属性。

可复制代码:
// ES5实现const
function _const (obj, key, value) {

  Object.defineProperty(obj, key, {

    configurablefalse// 可配置性

    getfunction() {

      return value
    },

    setfunction(data) {

      if(value !== data) {

        throw new TypeError('Assignment to constant variable')
      } else {

        return data
      }

    }
  })
}

二 请用ES5实现call

分析:

call的主要作用是改变函数中this指向并调用函数,函数入参为枚举型,并且,改变this指向后并不返回新的函数。基于这些特点,可做如下实现:(如果没有接触过,很难想到会这么写)

可复制代码:
// call
Function.prototype.myCall = function(context = window, ...args) {

  const key = Symbol('新增的独一无二的属性,防止覆盖原有属性'// 新建一个属性key
  context[key] = this // 新增的属性的值赋值为this
  const res = context[key](...args) // 通过隐式绑定的方式调用函数
  delete context[key] // 删除新增的key

  return res //返回函数调用的返回值
}

三 请用ES5实现apply

分析:

apply的主要作用是改变函数中this指向并调用函数,函数入参为类数组,并且,改变this指向后并不返回新的函数。基于这些特点,可做如下实现:(写法基本同call,只是入参形式变了)

可复制代码:

// apply
Function.prototype.myApply = function(context = window, args) {

  const key = Symbol('建立一个独一无二的属性,防止覆盖原有属性'// 新建一个属性key
  context[key] = this // 新增的属性赋值为this
  const res = context[key](...args) // 将传入的参数数组展开调用

  delete context[key]

  return res //返回函数调用的返回值
}

四 请用ES5实现bind

分析:

bind的特点是,只是改变函数this指向,并不调用函数,并且最终返回的是一个新的函数,基于此可做如下实现:

可复制代码:

// bind
Function.prototype.myBind = function(context, ...fArg) {

  const fn = this
  fArg = fArg || []

  return function newFn(...newFnArgs) {

    if(this instanceof newFn) {

      return new fn(...args, ...newFnArgs)
    }

    return fn.apply(context, [...fArg, ...newFnArgs])
  }
}

五 请输出1-1000内所有的质数

分析:

质数指的是只能被1和本身除尽,并且没有其他约数的自然数。

可复制代码:

// 判断质数
function isPrime(n) {

    if(n<=3 && n > 1) { return n  }

    if (n % 2 == 0 || n % 3 == 0) { return false; }

    for (var  i = 5; i * i <= n; i += 6) {

        if (n % i == 0 || n % (i + 2 == 0)) { return false; }
    }

    return n;
}

//  输出1-1000质数
var res = []

for(let i=2;i<1000;i++) {

  if(isPrime(i)) {

    res.push(isPrime(i))
  }
}

console.log(res)

文末

今日分的手写就总结到这,虽然不多,但够经典。一日一钱,千日千钱,绳锯木断,水滴石穿。

只写看得懂、读得懂、有价值的技术文章;看完觉得有收获,点赞 + 关注,平台会为你推荐更多优质主题文章;

★★★为确保面试前能找到本篇文章进行复习,请收藏或点赞,日后即可在“我的动态”中找到本文。