# javascript 特性挖掘

返回:es next 基础

# 一、逗号运算符

是用于分隔表达式并返回链中最后一个表达式的运算符。

let oo = (1, 2, 3);
console.log(oo); // 3
1
2

我们在 for 循环中看到这个:

for(let i = 0, ii = 1; i< 10; i++, ii--) { ... }
1

# 二、in

in 是用于检查对象中属性是否存在的关键字。我们在 for..in 循环中使用了它,但没有意识到,其实 in 也是一个关键字

如果对象上存在属性,则 in 将返回 true ,否则将返回 false。

const o = {
  prop: 1,
};
console.log("prop" in o); // true
1
2
3
4

# 三、Array 构造函数

const arr = new Array(1, 2, 3);
// 和

const arr = [1, 2, 3];
1
2
3
4

但使用 new Array() 有一个问题,例如:

var a = new Array(10, 20);
a[0]; // 返回 10
a.length; // 返回 2
1
2
3

但:

var a = new Array(10);
a[0]; // 返回 undefined
a.length; // 返回 10
1
2
3

当你仅给 Array 构造函数一个整数(大于等于 0 的整数,否则将会报错)时,才会发生这种情况

# 四、Function 构造函数

在 JavaScript 中,我们定义如下函数:

const mul = (a, b) => a * b;

// 或
function mul(a, b) {
  return a * b;
}

// 或
const mul = function(a, b) {
  return a * b;
};
1
2
3
4
5
6
7
8
9
10
11

我们也可以这样做,来实现相同的功能:

const mul = new Function("a", "b", "return a * b");
1

Function 构造函数创建一个新的 Function 对象。直接调用此构造函数可用动态创建函数,但会遭遇来自 eval 的安全问题和相对较小的性能问题。然而,与 eval 不同的是,Function 构造函数只在全局作用域中运行。

# 五、数组解构

所以,我们将解构用于数组上:

const arr = [1, 2, 3];
const { 0: firstA, 1: secA, 2: thirdA } = arr;

firstA; // 1
secA; // 2
thirdA; // 3
1
2
3
4
5
6
const [first, second, third] = arr;

first; // 1
second; // 2
third; // 3
1
2
3
4
5

注意:应尽可能避免知道数组中的特定位置信息(开始、结束索引是什么)。

# 六、使用 length 属性减少数组内容

const arr = [1, 2, 3];
arr.length; // 3
arr.length = 1;
arr; // [1]

arr.length = 5;
arr; // [1, empty × 4]
1
2
3
4
5
6
7

# 七、Arguments

我们可以使用 arguments 对象获取传递给函数的参数,而无需在函数中明确定义 arguments 变量

function myFunc() {
  console.log(arguments[0]); // 34
  console.log(arguments[1]); // 89
}

myFunc(34, 89);
1
2
3
4
5
6

arguments 对象是数组索引的。也就是说,属性是数字,因此可以通过键引用进行访问。

arguments 对象是从 Arguments 类实例化的,该类具有一些很酷的属性。

  • arguments.callee.name 指当前正在调用的函数的名称。
function myFunc() {
  console.log(arguments.callee.name); // myFunc
}

myFunc(34, 89);
1
2
3
4
5
  • arguments.callee.caller.name 是指调用当前执行函数的函数的名称。
function myFunc() {
  console.log(arguments.callee.name); // myFunc
  console.log(arguments.callee.caller.name); // myFuncCallee
}

(function myFuncCallee() {
  myFunc(34, 89);
})();
1
2
3
4
5
6
7
8

# 八、跳过 ()

你是否知道实例化对象时可以跳过方括号 () ?

例如:

class D {
  logger() {
    console.log("D");
  }
}

// 一般情况下,我们这么做:
new D().logger(); // D

// 其实,我们可以跳过 ():
new D().logger(); // D
// 并且它可以正常运行
1
2
3
4
5
6
7
8
9
10
11
12

即使在内置类中,括号也是可选的:

new Date().getDay();
new Date().getMonth();
new Date().getYear();
1
2
3

# 九、void

void 是 JS 中的关键字,用于评估语句并返回未定义。

class D {
  logger() {
    return 89;
  }
}

const d = new D();

console.log(void d.logger()); // undefined
1
2
3
4
5
6
7
8
9

logger 方法应该返回 89 ,但是 void 关键字将使其无效并返回 undefined

# 十、通过 proto 继承

_proto_ 是从 JavaScript 中的对象继承属性的方法。__proto__ 是 Object.prototype 的访问器属性,它公开访问对象的 [[Prototype]]

__proto__ 将其 [[Prototype]] 中设置的对象的所有属性设置为目标对象。

const l = console.log;
const obj = {
  method: function() {
    l("method in obj");
  },
};
const obj2 = {};
obj2.__proto__ = obj;
obj2.method(); // method in obj
1
2
3
4
5
6
7
8
9

# 十一、一元运算符 +

一元 + 运算符将其操作数转换为数字类型。

+"23" + // 23
{} + // NaN
null + // 0
undefined + // NaN
{ valueOf: () => 67 } + // 67
  "nnamdi45"; // NaN
1
2
3
4
5
6

当我们希望将变量快速转换为 Number 时,这非常方便。

# 十二、一元运算符 -

一元运算符 - 将其操作数转换为 Number 类型,然后取反。

该运算符将一元 + 运算符的结果取反。首先,它将操作数转换为其 Number 值,然后取反该值。

-"23"; // -23
1
-{} // NaN
-null // -0
-undefined // NaN
-{ valueOf: () => 67 } // -67
-"nnamdi45" // NaN
1
2
3
4
5

如果转换为数值的结果为 NaN ,则不会应用取反。

取负 +0 产生 -0 ,取负 -0 产生 +0 。

- +0 // -0
- -0 // 0
1
2

# 十三、指数运算符 **

我们可以使用 ** 运算符在 JS 中进行相同的操作:

2 ** 3 // 8
9 ** 3 // 729
1
2