implementationJSON.stringify

JSON.stringify(value[, replacer[, space]]) MDN

Basic knowledge:

  • Arrays hold primitive data types (string.number.boolean) toStringReturns the values in the array, such as[1,2,'3', 'a ', 'b']. ToString () ==> 1,2,3,a,b
  • Properties that are not enumerable are ignored

Code parsing points:

  • The value is of typefunction.undefinedIs returned directlyundefined
  • The value is of typestringYou need to add""
  • The type of the value is object, and the value of the property inside the object isfunction.undefinedIt will be filtered directly, not transformed
  • The type of the value is object, and the value of the property inside the object isstringYou need to add""
  • The type of the value is object, and the value of the property inside the object isobjectObject to recursively call the transform method
  • The value is of type array, and the returned value contains[]
  • The value is of type object, and the returned value contains{}
function jsonToString(obj) {
            const _objType = typeof obj;
            if(_objType ! = ='object') {
                if(/function|undefined/.test(_objType)) {
                    return undefined;
                } else if(/string/.test(_objType)) {
                    obj = '"'+ obj +'"';
                }
                return String(obj);
            } else {
                let v = ' ', 
                    json = [], 
                    isArr = Array.isArray(obj);
                for(let k in obj) {
                    v = obj[k];
                    let _vType = typeof v;
                    if(/function|undefined/.test(_vType)) {
                        continue;
                    } else if(/string/.test(_vType)) {
                        v = '"'+ v +'"';
                    } else if(/object/.test(_vType)) {
                        jsonToString(v);
                    }
                    json.push((isArr ? ' ' : ('"'+ k +'" :)) + String(v));
                }
                return (isArr ? '[': '{') + String(json) + (isArr ? '] ' : '} '); }}Copy the code

implementationcall | apply

function.call(thisArg, arg1, arg2, ...) MDN

Basic knowledge:

  • Array.fromYou can turn an array of classes into an array
  • callapplyThe distinction iscallThe parameters are passed one by oneapplyThe parameter is passed as an array.callapplyapplyThe first parameter is thetaa, it is an arrayarrayThe first letter of the letter, soapplyThe array)

Code parsing points:

  • callThe first argument to the method is passednull“, which is equivalent to the transmissionwindowobject
  • callMethod is not passed an object (primitive data type) and is set to null by default{}
  • callMethod insidethisIs the calling method itself,thisIs a method (typeof this === 'function')
Function.prototype.call2 = function() {
    let _this = arguments[0] | |window;
    if(typeof_this ! = ='object') {
        _this = {};
    }
    let param = Array.from(arguments).slice(1);
    _this.fn = this;
    letresult = _this.fn(... param);delete _this.fn;
    return result;
}

Function.prototype.apply2 = function() {
    let _this = arguments[0] | |window;
    let param = arguments[1]?arguments[1] : [];
    _this.fn = this;
    letresult = _this.fn(... param)delete _this.fn;
    return result;
}
Copy the code

implementationbind

function.bind(thisArg[, arg1[, arg2[, ...]]]) MDN

A new function is created. When the new function is called, the first argument to bind() will be this when it runs, and the subsequent sequence of arguments will be passed as its arguments before the arguments passed. (From MDN)

Basic knowledge:

  • bindThe first argument to the method is from the binding methodthisPoint to the
  • bindA method return is a method
  • bindMethod parameters returned by a method can also be passed to the original method as parameters

Code parsing points:

  • prototypePrototypes need to be noticed
Function.prototype.bind2 = function() {
    let content = arguments[0] || null;
    let _fn = this;
    let params = Array.from(arguments).slice(1);
    let resFn = function() {
        params = params.concat(Array.from(arguments));
        _fn.apply(content, params);
    }
    resFn.prototype = this.prototype;
    return resFn;
}
Copy the code

implementationnew

new constructor[([arguments])] MDN

New creates the instance object using the constructor, adding the this attribute and method to the instance object

Basic knowledge

  • Array.prototype.shift.call(arguments)Make class arrays available to use the methods of the previous arrayshift

Code parsing point

  • The first argument to a new method must be a method
  • newOperator returns an object
  • The originalfnMethod returns an objectfnThe default value is the newly created object
  • A new object__proto__Point to functionprototype
function newF() {
    // Get the first argument to the newF method
    const fn = Array.prototype.shift.call(arguments);
    // If the first argument to the newF method is not a method, an exception is thrown
    if(typeoffn ! = ='function') {
        throw fn + 'Method first argument must be method';
    }
    // Get the other arguments passed by the newF method and put them in an array
    const params = Array.prototype.slice.call(arguments.0);
    // Create a new object
    const res = {};
    // The new object's __proto__ is assigned to fn.prototype
    res.__proto__ = fn.prototype;
    // Call the fn method passed in with apply
    const ret = fn.apply(res, params)
    // If the original method returns an object, the object is returned; otherwise, the newly created object is returned
    return typeof ret === 'object' ? ret : res;
}
Copy the code

Implementing javascript overloading

The overload case is a classic use of closures where the function name is the same, but the logic of the call or the result of the call will be different depending on the number of arguments passed in

Basic knowledge

  • Closures (A function that can access a function’s internal variables is a closure)
  • Recursion (continuous loop calling itself)

Code parsing points (see comments code parsing)

((a)= > {
    //IIFE+ arrow function, it is a good habit to wrap up the code you want to write
    When a function is a property of an object, it is called a method of that object.

    /** * object: an object to which an overloaded function (method) can then be added * name: the name of the overloaded function (method) * fn: the logic of the function added to object to participate in the overload * closure */
    function overload(object, name, fn) {
        var oldMethod = object[name];// Save the old function, the soul of this method, multiple fn series
        object[name] = function() {
            // Code parsing
            // The first time the object[name] method is called, arguments length is 0, and fn (fn2) has two arguments
            // if oldMethod is a method, oldMethod is equal to object[name]
            // Call the object[name] method again, but the object[name] method of the last assignment
            // The last fn was fn1. Fn1 (1); arguments (0); else if (arguments)
            // if oldMethod is called overload for the first time, fn is equal to fn0
            // Arguments to fn0 are equal to 0. Just call fn.apply to pass in the parameters
            
            // fn.length is the number of arguments when fn is defined and arguments.length is the number of arguments when overloaded methods are called
            if (fn.length === arguments.length) {// If the number of parameters matches
                return fn.apply(this.arguments);// call the specified function fn
            } else if (typeof oldMethod === "function") {// If the number of parameters does not match
                return oldMethod.apply(this.arguments);Note: when overload() is called many times, there are old functions in the old function, nesting layer upon layer, recursively executing if.. Else check until fn with a matching number of arguments is found}}; }// When no parameter is passed
    function fn0() {
        return "no param";
    }
    // Pass 1 parameter
    function fn1(param1) {
        return "1 param:" + param1;
    }
    // If two parameters are passed, the name matching param1 and param2 is returned
    function fn2(param1, param2) {
        return "2 param:" + [param1, param2];
    }

    let obj = {};// Define an object so that its methods can be overridden later

    overload(obj, "fn", fn0);// add the first overloaded function to obj
    overload(obj, "fn", fn1);// add the second overloaded function to obj
    overload(obj, "fn", fn2);// add a third overloaded function to obj

    console.log(obj.fn());//>> no param
    console.log(obj.fn(1));//>> 1 param:1
    console.log(obj.fn(1.2));/ / > > 2 param: 1, 2}) ();Copy the code