Home >Web Front-end >JS Tutorial >JavaScript tips
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]
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]
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]
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 ,
One of our common solutions is to pass null or undefined.
method('parameter1', null, 'parameter3') // or method('parameter1', undefined, 'parameter3');
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']); // 代码执行了...
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]
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]
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() }
At this time, you can use short circuit like this:
condition && dosomething()
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
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
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
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
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[, ...]]])
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
9. Get the file extension
Solution 1: Regular expression
function getFileExtension1(filename) { return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename)[0] : undefined; }
Solution 2: String's split method
function getFileExtension2(filename) { return filename.split('.').pop(); }
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'
How is this implemented?
10. Prevent unapply attacks
// 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; }; }
上面的函数声明忽略了函数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); }());
11.Javascript多维数组扁平化
下面是将多位数组转化为单一数组的三种不同方法。
var arr = [[1, 2],[3, 4, 5], [6, 7, 8, 9]];
期望结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
解决方案1:使用concat()和apply()
var newArr = [].concat.apply([], arr); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
解决方案2:使用reduce()
var newArr = arr.reduce(function(prev, curr) { return prev.concat(curr); }); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
解决方案3:使用 ES6 的展开运算符
var newArr = [].concat(...arr); console.log(newArr); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
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] === 'function') { 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('optionA:', optionA); console.log('optionB:', optionB); console.log('callback:', callback); /* 你想做的逻辑 */ } // ES6语法书写更简短 function example(...args) { // 第一个参数为错误参数 const err = args.shift(); // 如果最后一个参数是函数,则它为回调函数 const callback = (typeof args[args.length-1] === 'function') ? 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); /* 你想做的逻辑 */ }
推荐教程:《JS教程》
The above is the detailed content of JavaScript tips. For more information, please follow other related articles on the PHP Chinese website!