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)
with
Statement extends the scope chain of a statement. It is not recommended because of compatibility issues.
eval
Allows 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 strict
to 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"