建站教程

建站教程

Products

当前位置:首页 > 建站教程 >

关于JavaScript不得不知道的技巧(原生JavaScript创建不可变对象的方法简单示例)

GG网络技术分享 2025-03-18 16:14 0


关于JavaScript不得不知道的技巧

在 JavaScript 中 数组(Array)随处可见,使用ECMAScript 6 中的新特性 扩展运算符 我们可以做很多很棒事情。

1. 迭代一个空数组

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]

2. 给方法传一个空参数

如果你想调用一个方法,并不填其中的一个参数时,JavaScript 就会报错。

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

一个我们常用的解决方法是传递 null 或 undefined。

method('parameter1', null, 'parameter3') // or

method('parameter1', undefined, 'parameter3');

根据 ES6 中对扩展运算符的介绍,有一个更简洁的方法可以将空参数传递给一个方法。正如上面所提到的,数组是松散的,所以给它传空值是可以的,我们正是用到了这个优点。

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

3. 数组去重

我一直不明白为什么数组不提供一个内置函数可以让我们方便的取到去重以后的值。扩展运算符帮到了我们,使用扩展运算符配合 Set可以生成一个不重复的数组。

const arr = [...new Set([1, 2, 3, 3])];

// [1, 2, 3]

4.从后向前获取数组元素

如果你想从后向前获取一个数组的元素,可以这样写:

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.短路条件句

如果你想在某个条件逻辑值为true时,执行某个函数,就像这样:

if (condition) {

dosomething()

}

这时,你可以这样子运用短路:

condition && dosomething()

6.用操作符 “||” 来设置默认值

如果你必须给一个变量赋默认值,可以简单的这样写:

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.在相等比较中使用 Object.is()

我们都知道 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

8.给一个函数 Bind 对象

我们经常需要将一个对象绑定到一个方法的 this 上。在 JS 中,如果你想要调用一个函数并指定它的 this 时可以使用 bind 方法。

Bind 语法

fun.bind(thisArg[, arg1[, arg2[, ...]]])

参数

thisArg

当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。

arg1, arg2, …

当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。

返回值

返回由指定的this值和初始化参数改造的原函数拷贝

JS 中的实例

9.获取文件拓展名

解决方法 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方法

这是如何实现的呢?

  • String.lastIndexOf() 方法返回指定值(本例中的'.')在调用该方法的字符串中最后出现的位置,如果没找到则返回 -1。
  • 对于'filename'和'.hiddenfile',lastIndexOf的返回值分别为0和-1无符号右移操作符(»>) 将-1转换为4294967295,将-2转换为4294967294,这个方法可以保证边缘情况时文件名不变。
  • String.prototype.slice() 从上面计算的索引处提取文件的扩展名。如果索引比文件名的长度大,结果为""。

10.预防unapply攻击

重写内置对象的原型方法,外部代码可以通过重写代码达到暴漏和修改已绑定参数的函数。这在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);

}());

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]

原生JavaScript创建不可变对象的方法简单示例

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

提示:如果希望在尝试修改不可变对象时抛出错误,请使用严格模式。

原生JavaScript创建不可变对象的方法简单示例 (https://www.wpmee.com/) javascript教程 第1张

标签:

提交需求或反馈

Demand feedback