Front-end advanced JS function enhancement and object enhancement

JS function enhancement

Function properties

A function in JavaScript is also an object, so the object can have properties and methods. It has some default properties.

  • name function name
  • length The number of function parameters (ES6 ... syntax will not be counted)
  • arguments is an array-like object that can be retrieved using indexing.
  • rset

PS: Arrow functions do not bind Arguments objects

Common methods for converting arguments to array objects

The common method is to iterate the contents into a new array one by one.

    let newArray = []
    // arguments
    function foo1(m, n) {
    
    
        for (var arg of arguments) {
    
    
            newArray.push(arg)
        }
        // arguments类似数组的对象(它可以通过索引来获得对象)
        console.log(newArray)
    }
    foo1(1, 2)

Methods in ES6

  • Array.form() can be converted into an array by passing in an iterable object
  • object structure ...to copy
        // 方法2
         var newArray1 = Array.from(arguments)
        // 方法3
        var newArray = [...arguments]

rset

If the last parameter is prefixed with ... then it will put the remaining parameters into that parameter and as an array

function foo1(m, n, ...arg)
  • The arguments object contains all the actual parameters passed to the function but is not an array object and needs to be converted.
  • The rest parameter is a real array and can perform all array operations.
  • arguments is a data structure provided in the early days for the convenience of obtaining all parameters. Rest parameters are provided in ES6 and are expected to replace arguments.

Understanding and applying pure functions

side effect:

When executing a function, in addition to returning the function value, it also has additional effects on the calling function, such as modifying global variables, modifying parameters, or changing external storage.

Understanding pure functions

  • When the same value is input, the same output is produced, so a pure function cannot call upper-layer properties through the closure feature, because the function output content will change with the upper-layer properties.
  • The output of the function has nothing to do with information other than the input value and has nothing to do with the external output of the device.
  • This function cannot have semantically observable "side effects"
Pure function identification case
  • slice: When slice intercepts an array, it does not perform any operations on the original array, but generates a new array.
  • splice: splice intercepts an array, returns a new array, and also modifies the original array.
    var names = ["abc", "nba", "nbc", "cbd"]
    var newNames = names.slice(0, 2)
    var newNames1 = names.splice(0, 2)
    console.log(newNames);
    console.log(newNames1);
Advantages of pure functions
  • Stable and can be used with confidence
  • Ensure the purity of functions and simply implement your own business logic, with few dependencies on various external factors.
  • When using it, you need to ensure that the input content is not arbitrarily tampered with, and you need to be sure that the input will have a certain output.

The understanding and application of currying

An important concept of functional programming. It is a high-level technology that operates on functions and is also used in other programming languages.

Calling a function by passing only part of its parameters and having it return a function to handle the remaining parameters is called currying.

   // 普通的函数
    function foo(x, y, z) {
    
    
        console.log(x + y + z);
    }
    foo(10, 20, 30)

    // 柯里化的结果
    function kelifoo(x) {
    
    
        return function (y) {
    
    
            return function (z) {
    
    
                console.log(x + y + z);
            }
        }
    }
    kelifoo(10)(20)(30)

//箭头函数写法
 var foo2 = x => y => z => {
    
     console.log(x + y + z) }
Automatic currying function
    // 需要转化的例子
    function sum(num1, num2) {
    
    
        console.log(num1 + num2);
        return num1 + num2
    }
    // 自动柯里化函数
    function hyCurrying(fn) {
    
    
        // 1 继续返回一个新的函数 继续接受函数
        // 2 直接执行 fn 函数
        function curryFun(...args) {
    
    
            if (args.length >= fn.length) {
    
    
                // 执行第二种操作
                return fn.apply(this, args)
            } else {
    
    
                return function (...newArgs) {
    
    
                    return curryFun.apply(this, args.concat(newArgs))
                }
            }
        }
        return curryFun
    }
    // 对其他函数柯里化
    var sumCurry = hyCurrying(sum)
    sumCurry(10)(5)
    sumCurry(10, 5)

Currying functions are only needed in certain special scenarios. Its performance is not high and it may cause memory leaks in closures, so you need to pay attention when using it.

Understanding and applying combination functions

When we need to call two functions nestedly, in order to facilitate reuse, we can write a combined function

var sum = pow(double(12)) 

We can write a general combination function to make it more convenient for us to use the combination function. In fact, the idea is to simply put the function into the array to determine the boundary order and execute it.

    function sum(num) {
    
    
        return num * 2
    }
    function pow(num) {
    
    
        return num ** 2
    }

    function composeFn(...fns) {
    
    
        // 边界判断
        var length = fns.length
        if (length < 0) {
    
    
            return
        }
        for (let i = 0; i < length; i++) {
    
    
            var fn = fns[i]
            if (typeof fn != "function") {
    
    
                throw new Error(`index postion ${
      
      i} must be function`)
            }
        }
        //轮流执行函数 返回结果对象
        return function (...args) {
    
    
            var result = fns[0].apply(this, args)
            for (let i = 1; i < length; i++) {
    
    
                var fn = fns[i]
                result = fn.apply(this, [result])
            }
            return result
        }
    }
    var newfn = composeFn(sum, pow)
    console.log(newfn(5)); //100

with statement, eval function (expanding knowledge)

withStatement extends the scope chain of a statement. It is not recommended because of compatibility issues.

evalAllows execution of a code string. It is a special function that can execute the incoming string as js code.

  • Poor readability
  • Risk of injection
  • Having to go through the interpreter will not result in engine optimization

Using strict mode

Limitations of js:

  • JavaScript continues to move forward without any compatibility issues;
  • New and old code This new mode is helpful for backward compatibility, but there are also problems.
  • That is, the creator will always retain the imperfections of js.

The ES5 standard proposes the concept of strict mode to detect and execute code in a more strict way.

You only need to add it at the beginning of the code or function use strictto turn on strict mode.

JS object enhancement

data attribute descriptor

Our attributes are generally defined inside the object or added directly to the object, but in this way we cannot impose some restrictions on the attributes, such as whether this attribute can be deleted through delete, and whether it can be traversed during for-in traversal. etc.

PS: For more precise operation control of an attribute, you can use attribute descriptors.

  • Property descriptors can be used to accurately add or modify object properties.
  • Object.defineProperty to add or modify properties

This method will directly define a new property on an object, or modify an existing property of an object, and return this object.

 Object.defineProperty() 
Property descriptor classification

Divided into two categories:

  • data attributes
  • access attribute
data attribute descriptor

Configurable: Indicates whether the attribute can be deleted through delete and whether its characteristics can be modified.

  • True when using object definition attributes
  • Defaults to false when defined using property descriptors

Enumerable: Indicates whether the attribute can be returned through for-in or Object.keys();

  • True when defined within a direct object
  • Defined as false via property descriptor

Writable: Indicates whether the value of the attribute can be modified;

  • True when defined within a direct object
  • Defined as false via property descriptor

value: The value of the attribute. This value will be returned when the attribute is read. When the attribute is modified, it will be modified.

  • By default this value is undefined

Use Cases

    var obj = {
    
    
        name: "whit",
        age: 12
    }
    Object.defineProperty(obj, "name", {
    
    
        configurable: false,
        enumerable: false,
        writable: false,
        value: "1234"
    })
access attribute descriptor

Configurable&Enumerable It is also an access attribute descriptor

get: The function that will be executed when getting the attribute. Default is undefined

set: Function that will be executed when setting the property. Default is undefined

Define multiple properties at the same time

    // 多个属性调用
    Object.defineProperties(obj, {
    
    
        name: {
    
    
            configurable: false,
            enumerable: false
        },
        age: {
    
    
            enumerable: false,
            writable: false,
        }
    })

Object method supplement

Get the object's property descriptor:

  • getOwnPropertyDescriptor
  • getOwnPropertyDescriptors

Prevent objects from extending new attributes: preventExtensions

  • Adding new properties to an object will fail (an error will be reported in strict mode);

Sealed object, does not allow configuration and deletion of properties: seal

  • What actually happens is calling preventExtensions
  • And set the existing properties to configurable:false

Freezes the object and does not allow modification of existing properties: freeze

  • Actually calling seal
  • And set the existing properties to writable: false

Code examples

    // 阻止对象的拓展
    Object.preventExtensions(obj)
    obj.address = 12
    //密封对象 不能进行配置
    Object.seal(obj)
    delete obj.name
    // 冻结对象
    Object.freeze(obj)
    obj.name = "ske"

Guess you like

Origin blog.csdn.net/doomwatcher/article/details/129328062