美文网首页
小哥带来的学习

小哥带来的学习

作者: 余音绕梁_0809 | 来源:发表于2022-04-07 17:49 被阅读0次

    1、写一个方法:不定参数求和

    前言:

    1、类数组对象: 在javascript中,数组是一个特殊的对象,其property名为正数组,且其length属性会随着数组成员的增减而发生变化,同时又从arry构造函数中继承一些用于进行数组操作的方法,而对于一个普通的对象来说,如果它的所有property名均为正整数,同事也有相应的length属性,那么虽然该对象并不是由Array构造函数所创建的,它依然呈现出数组的行为,在这种情况下,这些对象被称为"类数组对象"
    2、Array.from()对一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。

    function Sum() {
        // 1、获取参数个数---arguments(类数组对象)
        // 2、类数组对象转化为数组
        //      [...arguments]
        //      Array.from(arguments)
        // 3、数组求和
        //  return eval(Array.from(arguments).join("+"));
            return [...arguments].reduce((pre,cur) => {
                return pre + cur
            })
    } 
    console.log(Sum(1,2,3,4));//10
    

    //arguments

    image.png

    2、创建一个长度为100的数组

    • length=100
    image.png
    • new Array()
    image.png
    • Array.from()
    image.png
    注:上面两种拿到的数组,都是empty,没有实际的使用效果; 使用Object.keys()可以拿到数组的index去生成数组

    3、手写一个 new

    function selfNew(param){
        if(typeof param !== 'function') return '要是一个function';
        
        selfNew.target = param;
    
        let newObj = Object.create(param.prototype);
        console.log(newObj,'newObjnewObjnewObj');
    
    
        let arr = [...arguments].slice(1,arguments.length)
        console.log(arr, 'arr');
    
        let paramResult =  param.apply(newObj, arr);
        console.log(paramResult,'paramResultparamResultparamResultparamResult');
    
        var isObject = typeof paramResult === 'object' && paramResult !== null;
        var isFunction = typeof paramResult === 'function';
         if(isObject || isFunction){
            return paramResult;
        }
        return newObj;
    }
    function newOperator(ctor){
        if(typeof ctor !== 'function'){
          throw 'newOperator function the first param must be a function';
        }
        newOperator.target = ctor;
    
        var newObj = Object.create(ctor.prototype);
    
        console.log(newObj,'newObj-newOperator');
    
    
    
        var argsArr = [].slice.call(arguments, 1);
        console.log(argsArr,'argsArr-newOperator');
    
        // 重置new.target
        newOperator.target = null;
    
        var ctorReturnResult = ctor.apply(newObj, argsArr);
        console.log(ctorReturnResult,'ctorReturnResult-newOperator');
    
        var isObject = typeof ctorReturnResult === 'object' && ctorReturnResult !== null;
        var isFunction = typeof ctorReturnResult === 'function';
        if(isObject || isFunction){
            return ctorReturnResult;
        }
        return newObj;
    }
    function Student(name, age) {
        this.name = name;
        this.age = age;
    }
    Student.prototype.doSth = function() {
        console.log(`我是${this.name}`);
    };
    
    newStudent = new Student('new',18);
    myStudent = selfNew(Student, 'selfNew',18);
    operatorStudent = newOperator(Student, 'newOperator',18);
    
    console.log(newStudent,newStudent.doSth(),'newStudent');
    
    console.log(myStudent,myStudent.doSth(),'myStudent');
    
    console.log(operatorStudent,operatorStudent.doSth(),'operatorStudent');
    //newOperator方法来自于 https://juejin.cn/post/6844903704663949325
    

    对target进行拦截处理,以防构造函数中含有构造函数,target的指向会有问题

     const newOperator = (function () {
          const _newStack = [];
          function newOperator(ctor) {
            // 设定new.target
            newOperator.target = ctor;
            // 生成新的对象,其隐式原型指向构造函数的原型对象
            const obj = Object.create(ctor.prototype);
            // 执行构造函数,并返回结果
            const result = ctor.apply(
              obj,
              Array.prototype.slice.call(arguments, 1)
            );
    
            // 重置new.target
            newOperator.target = null;
            // 判断最终返回对象
            return (typeof result === "object" && result !== null) ||
              typeof result === "function"
              ? result
              : obj;
          }
          // 设定target的get、set方法
          Reflect.defineProperty(newOperator, "target", {
            get() {
              return _newStack[_newStack.length - 1];
            },
            set(target) {
              if (target == null) {
                _newStack.pop();
              } else {
                _newStack.push(target);
              }
            },
          });
          return newOperator;
        })();
        function B() {
          if (newOperator.target === B) {
            console.log("new调用 B");
          } else {
            console.log("非new调用 B");
          }
          return { balabala: 123 };
        }
    
        function A() {
          const b = newOperator(B);
          if (newOperator.target === A) {
            console.log("new调用 A");
          } else {
            console.log("非new调用 A");
          }
        }
    //此优化为 https://juejin.cn/post/6844903704663949325 网友的评论
    

    4.手写call、apply、bind

    • call(参数用逗号隔开,不需要自调用)
    Function.prototype.myCall = function(context, ...args) {
        // 此时this指的是当前调用myCall的函数
        if(typeof this !== 'function') return "It's must be a function"
    
        // 绑定的对象是否存在,不存在 this指向window
        if(!context) context = window;
    
        // 创建一个唯一的fn作为绑定对象的属性
        const fn = Symbol()
    
        // 把this指向fn
        context[fn] = this;
    
        // 用其他的参数,调用fn拿到返回值
        const result = context[fn](...args)
        // 清除对象上的fn属性
        delete context[fn]
        
        return result
    
    }
    let ceshi = function(name, age, className) {
        this.name = name,
        this.age = age,
        this.className = className
    }
    let obj = {
        name: 'xiaohua',
        age: 18
    }
    let school = {
        className: 2,
        age: 18
    }
    ceshi.myCall(obj, '小花','2',6);
    ceshi.myCall(school, '3', 12,5);
    console.log(obj, school);
    
    image.png
    • apply(参数为数组,不需要自调用)
    Function.prototype.myApply = function (context, args) {
         // 此时this指的是当前调用myCall的函数
         if(typeof this !== 'function') throw "It's must be a function"
    
         // 绑定的对象是否存在,不存在 this指向window
         if(!context) context = window;
     
         // 创建一个唯一的fn作为绑定对象的属性
         const fn = Symbol()
     
         // 把this指向fn
         context[fn] = this;
        // 参数: 数组 || 类数组
        if (typeof args !== 'object' || !args.length ) throw console.error('参数类型错误');
         // 用其他的参数,调用fn拿到返回值 ---参数为类数组对象Array.from(args)
         const result = context[fn](...Array.from(args))
         // 清除对象上的fn属性
         delete context[fn]
         
         return result
     
    }
    let ceshi = function(name, age, className) {
        this.name = name,
        this.age = age,
        this.className = className
    }
    let obj = {
        name: 'xiaohua',
        age: 18
    }
    let school = {
        className: 2,
        age: 18
    }
    ceshi.myApply(obj,['xiaohuaya',1,2])
    ceshi.myApply(school,['shiwoa',2,3])
    console.log(obj,school);
    
    image.png
    • bind(参数用逗号隔开,需要自调用)

    相关文章

      网友评论

          本文标题:小哥带来的学习

          本文链接:https://www.haomeiwen.com/subject/tvvpjrtx.html