Products
GG网络技术分享 2025-03-18 16:14 0
在 JavaScript 中 数组(Array)随处可见,使用ECMAScript 6 中的新特性 扩展运算符 我们可以做很多很棒事情。
JavaScript 中直接创建的数组是松散的,以至于会有很多坑。试着用数组的构造方法创建一个数组,你就会瞬间明白了。
const arr = new Array(4);
[undefined, undefined, undefined, undefined]
// 谷歌浏览器中是 [empty x 4]
你会发现,通过一个松散的数组去循环调用一些转换是非常难的。
const arr = new Array(4);
arr.map((elem, index) => index);
[undefined, undefined, undefined, undefined]
想要解决这个问题,你可以使用在创建新数组的时候使用 Array.apply。
const arr = Array.apply(null, new Array(4));
arr.map((elem, index) => index);
[0, 1, 2, 3]
如果你想调用一个方法,并不填其中的一个参数时,JavaScript 就会报错。
method('parameter1', , 'parameter3'); // Uncaught SyntaxError: Unexpected token ,
一个我们常用的解决方法是传递 null 或 undefined。
method('parameter1', null, 'parameter3') // or
method('parameter1', undefined, 'parameter3');
根据 ES6 中对扩展运算符的介绍,有一个更简洁的方法可以将空参数传递给一个方法。正如上面所提到的,数组是松散的,所以给它传空值是可以的,我们正是用到了这个优点。
method(...['parameter1', , 'parameter3']); // 代码执行了...
我一直不明白为什么数组不提供一个内置函数可以让我们方便的取到去重以后的值。扩展运算符帮到了我们,使用扩展运算符配合 Set可以生成一个不重复的数组。
const arr = [...new Set([1, 2, 3, 3])];
// [1, 2, 3]
如果你想从后向前获取一个数组的元素,可以这样写:
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]
如果你想在某个条件逻辑值为true时,执行某个函数,就像这样:
if (condition) {
dosomething()
}
这时,你可以这样子运用短路:
condition && dosomething()
如果你必须给一个变量赋默认值,可以简单的这样写:
var a
console.log(a) // undefined
a = a || 'default value'
console.log(a) // default value
a = a || 'new value'
console.log(a) // default value
我们都知道 JavasSript 是弱类型的,并且当我们使用==作比较时,在一些情况下由于类型转换或者说“把两个操作数中的一个转换成另一个,然后再比较”,会出现意想不到的结果。就像这样:
0 == ' ' //true
null == undefined //true
[1] == true //true
因此 JavaScript 中给我们提供了全等操作符 ===, 它比不全等操作符更加严格并且不会发生类型转换。但是用 === 来进行比较并不是最好的解决方案。你可能会得到:
NaN === NaN //false
ES6 中提供了新的 Object.is() 方法,它具有 === 的一些特点,而且更好、更精确,在一些特殊案例中表现的很好:
Object.is(0 , ' '); //false
Object.is(null, undefined); //false
Object.is([1], true); //false
Object.is(NaN, NaN); //true
我们经常需要将一个对象绑定到一个方法的 this 上。在 JS 中,如果你想要调用一个函数并指定它的 this 时可以使用 bind 方法。
Bind 语法
fun.bind(thisArg[, arg1[, arg2[, ...]]])
参数
thisArg
当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。
arg1, arg2, …
当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。
返回值
返回由指定的this值和初始化参数改造的原函数拷贝
解决方法 1: 正则表达式
function getFileExtension1(filename) {
return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename)[0] : undefined;
}
解决方法 2: String的split方法
function getFileExtension2(filename) {
return filename.split('.').pop();
}
这两种解决方法不能解决一些边缘情况,这有另一个更加强大的解决方法。
解决方法 3: String的slice、lastIndexOf方法
这是如何实现的呢?
重写内置对象的原型方法,外部代码可以通过重写代码达到暴漏和修改已绑定参数的函数。这在es5的方法下使用polyfill时是一个严重的安全问题。
上面的函数声明忽略了函数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);
}());
下面是将多位数组转化为单一数组的三种不同方法。
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]Javascript是一种灵活的语言,你可以重新定义任何东西,但是当项目变得复杂时,我们会发现可变数据结构的问题。随着JavaScript的最新版本的发布这种情况发生了改变。现在可以创建不可变的对象了。本文介绍如何用三种不同的方法来做。
对象的不变性意味着我们不希望对象在创建后即以任何方式更改(将它们设置为只读类型)。
假设我们需要定义一个car对象,并在整个项目中使用它的属性来执行操作。我们不能允许错误地修改任何数据。
const myTesla = { maxSpeed: 155, batteryLife: 300, weight: 2300 }; |
Object.preventExtensions() 防止扩展
此方法可防止向现有对象添加新属性,preventExtensions()是不可逆的操作,我们永远不能再向对象添加额外的属性。
Object.isExtensible(myTesla); // true Object.preventExtensions(myTesla); Object.isExtensible(myTesla); // false myTesla.color = \'blue\'; console.log(myTesla.color) // undefined |
Object.seal() 密封
它可以防止添加或删除属性,seal()还可以防止修改属性描述符。
Object.isSealed(myTesla); // false Object.seal(myTesla); Object.isSealed(myTesla); // true myTesla.color = \'blue\'; console.log(myTesla.color); // undefined delete myTesla.batteryLife; // false console.log(myTesla.batteryLife); // 300 Object.defineProperty(myTesla, \'batteryLife\'); // TypeError: Cannot redefine property: batteryLife |
Object.freeze() 冻结
它的作用与Object.seal()相同,而且它使属性不可写。
Object.isFrozen(myTesla); // false Object.freeze(myTesla); Object.isFrozen(myTesla); // true myTesla.color = \'blue\'; console.log(myTesla.color); // undefined delete myTesla.batteryLife; console.log(myTesla.batteryLife); // 300 Object.defineProperty(myTesla, \'batteryLife\'); // TypeError: Cannot redefine property: batteryLife myTesla.batteryLife = 400; console.log(myTesla.batteryLife); // 300 |
提示:如果希望在尝试修改不可变对象时抛出错误,请使用严格模式。
Demand feedback