offer收割机最新整理的JavaScript手写题

本文整理了包括call、apply、bind、继承、new、instanceof等JavaScript核心知识点的手写实现,涵盖数组扁平化、深拷贝、事件监听器等多个实战题目,是前端开发者面试必备的复习资料。
摘要由CSDN通过智能技术生成
1、call的实现
  • 第一个参数为null或者undefined时,this指向全局对象window,值为原始值的指向该原始值的自动包装对象,如 String、Number、Boolean
  • 为了避免函数名与上下文(context)的属性发生冲突,使用Symbol类型作为唯一值
  • 将函数作为传入的上下文(context)属性执行
  • 函数执行完成后删除该属性
  • 返回执行结果
Function.prototype.myCall = function(context,...args){
    let cxt = context || window;
    //将当前被调用的方法定义在cxt.func上.(为了能以对象调用形式绑定this)
    //新建一个唯一的Symbol变量避免重复
    let func = Symbol() 
    cxt[func] = this;
    args = args ? args : []
    //以对象调用形式调用func,此时this指向cxt 也就是传入的需要绑定的this指向
    const res = args.length > 0 ? cxt[func](...args) : cxt[func]();
    //删除该方法,不然会对传入对象造成污染(添加该方法)
    delete cxt[func];
    return res;
}
2、apply的实现
  • 前部分与call一样
  • 第二个参数可以不传,但类型必须为数组或者类数组
Function.prototype.myApply = function(context,args = []){
    let cxt = context || window;
    //将当前被调用的方法定义在cxt.func上.(为了能以对象调用形式绑定this)
    //新建一个唯一的Symbol变量避免重复
    let func = Symbol()
    cxt[func] = this;
    //以对象调用形式调用func,此时this指向cxt 也就是传入的需要绑定的this指向
    const res = args.length > 0 ? cxt[func](...args) : cxt[func]();
    delete cxt[func];
    return res;
}
3、bind的实现

需要考虑:

  • bind() 除了 this 外,还可传入多个参数;
  • bind 创建的新函数可能传入多个参数;
  • 新函数可能被当做构造函数调用;
  • 函数可能有返回值;

实现方法:

  • bind 方法不会立即执行,需要返回一个待执行的函数;(闭包)
  • 实现作用域绑定(apply)
  • 参数传递(apply 的数组传参)
  • 当作为构造函数的时候,进行原型继承
Function.prototype.myBind = function (context, ...args) {
    //新建一个变量赋值为this,表示当前函数
    const fn = this
    //判断有没有传参进来,若为空则赋值[]
    args = args ? args : []
    //返回一个newFn函数,在里面调用fn
    return function newFn(...newFnArgs) {
        if (this instanceof newFn) {
            return new fn(...args, ...newFnArgs)
        }
        return fn.apply(context, [...args,...newFnArgs])
    }
}

测试

let name = '小王',age =17;
let obj = {
    name:'小张',
    age: this.age,
    myFun: function(from,to){
        console.log(this.name + ' 年龄 ' + this.age+'来自 '+from+'去往'+ to)
    }
}
let db = {
    name: '德玛',
    age: 99
}

//结果
obj.myFun.myCall(db,'成都','上海');     // 德玛 年龄 99  来自 成都去往上海
obj.myFun.myApply(db,['成都','上海']);      // 德玛 年龄 99  来自 成都去往上海
obj.myFun.myBind(db,'成都','上海')();       // 德玛 年龄 99  来自 成都去往上海
obj.myFun.myBind(db,['成都','上海'])();   // 德玛 年龄 99  来自 成都, 上海去往 undefined
4、寄生式组合继承
function Person(obj) {
    this.name = obj.name
    this.age = obj.age
}
Person.prototype.add = function(value){
    console.log(value)
}
var p1 = new Person({name:"番茄", age: 18})

function Person1(obj) {
    Person.call(this, obj)
    this.sex = obj.sex
}
// 这一步是继承的关键
Person1.prototype = Object.create(Person.prototype);
Person1.prototype.constructor = Person1;

Person1.prototype.play = function(value){
    console.log(value)
}
var p2 = new Person1({name:"鸡蛋", age: 118, sex: "男"})
5、ES6继承
//class 相当于es5中构造函数
//class中定义方法时,前后不能加function,全部定义在class的protopyte属性中
//class中定义的所有方法是不可枚举的
//class中只能定义方法,不能定义对象,变量等
//class和方法内默认都是严格模式
//es5中constructor为隐式属性
class People{
  constructor(name='wang',age='27'){
    this.name = name;
    this.age = age;
  }
  eat(){
    console.log(`${this.name} ${this.age} eat food`)
  }
}
//继承父类
class Woman extends People{ 
   constructor(name = 'ren',age = '27'){ 
     //继承父类属性
     super(name, age); 
   } 
    eat(){ 
     //继承父类方法
      super.eat() 
    } 
} 
let wonmanObj=new Woman('xiaoxiami'); 
wonmanObj.eat();

//es5继承先创建子类的实例对象,然后再将父类的方法添加到this上(Parent.apply(this))。 
//es6继承是使用关键字super先创建父类的实例对象this,最后在子类class中修改this。
6、new的实现
  • 一个继承自 Foo.prototype 的新对象被创建。
  • 使用指定的参数调用构造函数 Foo,并将 this 绑定到新创建的对象。new Foo 等同于 new Foo(),也就是没有指定参数列表,Foo 不带任何参数调用的情况。
  • 由构造函数返回的对象就是 new 表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤1创建的对象。
  • 一般情况下,构造函数不返回值,但是用户可以选择主动返回对象,来覆盖正常的对象创建步骤
function Ctor(){
    ....
}

function myNew(ctor,...args){
    if(typeof ctor !== 'function'){
      throw 'myNew function the first param must be a function';
    }
    var newObj = Object.create(ctor.prototype); //创建一个继承自ctor.prototype的新对象
    var ctorReturnResult = ctor.apply(newObj, args); //将构造函数ctor的this绑定到newObj中
    var isObject = typeof ctorReturnResult === 'object' && ctorReturnResult !== null;
    var isFunction = typeof ctorReturnResult 
  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值