Home > Web Front-end > JS Tutorial > JavaScript tips

JavaScript tips

hzc
Release: 2020-06-12 10:38:16
forward
1813 people have browsed it

Arrays can be found everywhere in JavaScript, and we can do a lot of great things using the new feature spread operator in ECMAScript 6.

1. Iterate over an empty array


Arrays created directly in JavaScript are loose, so there will be many pitfalls. Try creating an array using the array constructor and you will understand it instantly.

const arr = new Array(4);
[undefined, undefined, undefined, undefined]
// 谷歌浏览器中是 [empty x 4]
Copy after login

You will find that it is very difficult to loop through some transformations through a loose array.

const arr = new Array(4);
arr.map((elem, index) => index);
[undefined, undefined, undefined, undefined]
Copy after login

To solve this problem, you can use Array.apply when creating a new array.

const arr = Array.apply(null, new Array(4));
arr.map((elem, index) => index);
[0, 1, 2, 3]
Copy after login

2. Pass an empty parameter to the method


If you want to call a method and do not fill in one of the parameters, JavaScript will report an error .

method('parameter1', , 'parameter3'); // Uncaught SyntaxError: Unexpected token ,
Copy after login

One of our common solutions is to pass null or undefined.

method('parameter1', null, 'parameter3') // or
method('parameter1', undefined, 'parameter3');
Copy after login

According to the introduction of the spread operator in ES6, there is a cleaner way to pass empty parameters to a method. As mentioned above, arrays are loose, so it is okay to pass null values ​​to them, and we take advantage of this.

method(...['parameter1', , 'parameter3']); // 代码执行了...
Copy after login

3. Array deduplication


I have never understood why the array does not provide a built-in function that allows us to easily obtain the deduplicated value. . The spread operator helps us. Using the spread operator with Set can generate a unique array.

const arr = [...new Set([1, 2, 3, 3])];
// [1, 2, 3]
Copy after login

4. Get array elements from back to front


If you want to get the elements of an array from back to front, you can write like this:

var arr = [1, 2, 3, 4]

console.log(arr.slice(-1)) // [4]
console.log(arr.slice(-2)) // [3, 4]
console.log(arr.slice(-3)) // [2, 3, 4]
console.log(arr.slice(-4)) // [1, 2, 3, 4]
Copy after login

5. Short-circuit conditional sentence


If you want to execute a function when the logical value of a certain condition is true, like this:

if (condition) {
  dosomething()
}
Copy after login

At this time, you can use short circuit like this:

condition && dosomething()
Copy after login

6. Use the operator "||" to set the default value


If You must assign a default value to a variable, which can be simply written like this:

var a

console.log(a) // undefined
a = a || 'default value'
console.log(a) // default value
a = a || 'new value'
console.log(a) // default value
Copy after login

7. Use Object.is() in equality comparison


We We all know that JavasScript is weakly typed, and when we use == for comparison, in some cases unexpected things will happen due to type conversion or "convert one of the two operands to the other and then compare" the result of. Like this:

0 == ' ' //true
null == undefined //true
[1] == true //true
Copy after login

So JavaScript provides us with the equality operator ===, which is more strict than the inequality operator and does not cause type conversion. But using === for comparison is not the best solution. You may get:

NaN === NaN //false
Copy after login

ES6 provides a new Object.is() method, which has some features of ===, is better and more precise, and performs well in some special cases. :

Object.is(0 , ' '); //false
Object.is(null, undefined); //false
Object.is([1], true); //false
Object.is(NaN, NaN); //true
Copy after login

8. Give a function Bind object


We often need to bind an object to this of a method. In JS, if you want to call a function and specify its this, you can use the bind method.

Bind Syntax

fun.bind(thisArg[, arg1[, arg2[, ...]]])
Copy after login

Parameters

thisArg

When the binding function is called, the The parameters will serve as this pointers to the original function when it is run.

arg1, arg2, …

When the bound function is called, these parameters will be passed to the bound method before the actual parameters.

Return value

Returns a copy of the original function modified by the specified this value and initialization parameters

Instance in JS

const myCar = {
 brand: 'Ford',
 type: 'Sedan',
 color: 'Red'
};

const getBrand = function () {
 console.log(this.brand);
};

const getType = function () {
 console.log(this.type);
};

const getColor = function () {
 console.log(this.color);
};

getBrand(); // object not bind,undefined

getBrand(myCar); // object not bind,undefined

getType.bind(myCar)(); // Sedan

let boundGetColor = getColor.bind(myCar);
boundGetColor(); // Red
Copy after login


9. Get the file extension

Solution 1: Regular expression

function getFileExtension1(filename) {
  return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename)[0] : undefined;
}
Copy after login

Solution 2: String's split method

function getFileExtension2(filename) {
  return filename.split('.').pop();
}
Copy after login

These two solutions cannot solve some edge cases. There is another more powerful solution.

Solution 3: String's slice and lastIndexOf methods

function getFileExtension3(filename) {
  return filename.slice((filename.lastIndexOf(".") - 1 >>> 0) + 2);
}

console.log(getFileExtension3(''));                            // ''
console.log(getFileExtension3('filename'));                    // ''
console.log(getFileExtension3('filename.txt'));                // 'txt'
console.log(getFileExtension3('.hiddenfile'));                 // ''
console.log(getFileExtension3('filename.with.many.dots.ext')); // 'ext'
Copy after login


How is this implemented?

  • ## The #String.lastIndexOf() method returns the last position where the specified value ('.' in this example) appears in the string that calls the method, or -1 if not found.

  • For 'filename' and '.hiddenfile', the return values ​​​​of lastIndexOf are 0 and -1 respectively. The unsigned right shift operator (»>) converts -1 to 4294967295, Convert -2 to 4294967294. This method can ensure that the file name remains unchanged in edge cases.

  • String.prototype.slice() Extracts the extension of the file from the index calculated above. If the index is greater than the length of the file name, the result is "".

10. Prevent unapply attacks


Rewrite the prototype method of the built-in object. External code can be exposed by rewriting the code. and functions that modify bound parameters. This is a serious security issue when using polyfills under es5's approach.

// bind polyfill 示例
function bind(fn) {
  var prev = Array.prototype.slice.call(arguments, 1);
  return function bound() {
    var curr = Array.prototype.slice.call(arguments, 0);
    var args = Array.prototype.concat.apply(prev, curr);
    return fn.apply(null, args);
  };
}


// unapply攻击
function unapplyAttack() {
  var concat = Array.prototype.concat;
  Array.prototype.concat = function replaceAll() {
    Array.prototype.concat = concat; // restore the correct version
    var curr = Array.prototype.slice.call(arguments, 0);
    var result = concat.apply([], curr);
    return result;
  };
}
Copy after login

上面的函数声明忽略了函数bind的prev参数,意味着调用unapplyAttack之后首次调用.concat将会抛出错误。

使用Object.freeze,可以使对象不可变,你可以防止任何内置对象原型方法被重写。

(function freezePrototypes() {
  if (typeof Object.freeze !== 'function') {
    throw new Error('Missing Object.freeze');
  }
  Object.freeze(Object.prototype);
  Object.freeze(Array.prototype);
  Object.freeze(Function.prototype);
}());
Copy after login

11.Javascript多维数组扁平化


下面是将多位数组转化为单一数组的三种不同方法。

var arr = [[1, 2],[3, 4, 5], [6, 7, 8, 9]];
Copy after login

期望结果:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
Copy after login

解决方案1:使用concat()和apply()

var newArr = [].concat.apply([], arr);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
Copy after login

解决方案2:使用reduce()

var newArr = arr.reduce(function(prev, curr) {
  return prev.concat(curr);
});
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
Copy after login

解决方案3:使用 ES6 的展开运算符

var newArr = [].concat(...arr);
console.log(newArr);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
Copy after login

12. 函数中如何使用可选参数(包括可选回调函数)


实例函数中第2个与第3个参数为可选参数

function example( err, optionA, optionB, callback ) {
        // 使用数组取出arguments
        var args = new Array(arguments.length);
        for(var i = 0; i < args.length; ++i) {
            args[i] = arguments[i];
        };
        
        // 第一个参数为错误参数
        // shift() 移除数组中第一个参数并将其返回
        err = args.shift();

        // 如果最后一个参数是函数,则它为回调函数
        // pop() 移除数组中最后一个参数并将其返回
        if (typeof args[args.length-1] === &#39;function&#39;) { 
            callback = args.pop();
        }
        
        // 如果args中仍有元素,那就是你需要的可选参数
        // 你可以像这样一个一个的将其取出:
        if (args.length > 0) optionA = args.shift(); else optionA = null;
        if (args.length > 0) optionB = args.shift(); else optionB = null;

        // 像正常一样继续:检查是否有错误
        if (err) { 
            return callback && callback(err);
        }
        
        // 打印可选参数
        console.log(&#39;optionA:&#39;, optionA);
        console.log(&#39;optionB:&#39;, optionB);
        console.log(&#39;callback:&#39;, callback);

        /* 你想做的逻辑 */

    }

    // ES6语法书写更简短
    function example(...args) {
        // 第一个参数为错误参数
        const err = args.shift();
        // 如果最后一个参数是函数,则它为回调函数
        const callback = (typeof args[args.length-1] === &#39;function&#39;) ? args.pop() : null;

        // 如果args中仍有元素,那就是你需要的可选参数你可以像这样一个一个的将其取出:
        const optionA = (args.length > 0) ? args.shift() : null;
        const optionB = (args.length > 0) ? args.shift() : null;
        // ... 重复取更多参数

        if (err && callback) return callback(err);

        /* 你想做的逻辑 */
    }
Copy after login

推荐教程:《JS教程

The above is the detailed content of JavaScript tips. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
js
source:juejin.im
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template