# javascript 特性挖掘
# 一、逗号运算符
是用于分隔表达式并返回链中最后一个表达式的运算符。
let oo = (1, 2, 3);
console.log(oo); // 3
2
我们在 for 循环中看到这个:
for(let i = 0, ii = 1; i< 10; i++, ii--) { ... }
# 二、in
in 是用于检查对象中属性是否存在的关键字。我们在 for..in 循环中使用了它,但没有意识到,其实 in 也是一个关键字
如果对象上存在属性,则 in 将返回 true ,否则将返回 false。
const o = {
prop: 1,
};
console.log("prop" in o); // true
2
3
4
# 三、Array 构造函数
const arr = new Array(1, 2, 3);
// 和
const arr = [1, 2, 3];
2
3
4
但使用 new Array() 有一个问题,例如:
var a = new Array(10, 20);
a[0]; // 返回 10
a.length; // 返回 2
2
3
但:
var a = new Array(10);
a[0]; // 返回 undefined
a.length; // 返回 10
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;
};
2
3
4
5
6
7
8
9
10
11
我们也可以这样做,来实现相同的功能:
const mul = new Function("a", "b", "return a * b");
Function 构造函数创建一个新的 Function 对象。直接调用此构造函数可用动态创建函数,但会遭遇来自 eval 的安全问题和相对较小的性能问题。然而,与 eval 不同的是,Function 构造函数只在全局作用域中运行。
# 五、数组解构
所以,我们将解构用于数组上:
const arr = [1, 2, 3];
const { 0: firstA, 1: secA, 2: thirdA } = arr;
firstA; // 1
secA; // 2
thirdA; // 3
2
3
4
5
6
const [first, second, third] = arr;
first; // 1
second; // 2
third; // 3
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]
2
3
4
5
6
7
# 七、Arguments
我们可以使用 arguments 对象获取传递给函数的参数,而无需在函数中明确定义 arguments 变量
function myFunc() {
console.log(arguments[0]); // 34
console.log(arguments[1]); // 89
}
myFunc(34, 89);
2
3
4
5
6
arguments 对象是数组索引的。也就是说,属性是数字,因此可以通过键引用进行访问。
arguments 对象是从 Arguments 类实例化的,该类具有一些很酷的属性。
arguments.callee.name指当前正在调用的函数的名称。
function myFunc() {
console.log(arguments.callee.name); // myFunc
}
myFunc(34, 89);
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);
})();
2
3
4
5
6
7
8
# 八、跳过 ()
你是否知道实例化对象时可以跳过方括号 () ?
例如:
class D {
logger() {
console.log("D");
}
}
// 一般情况下,我们这么做:
new D().logger(); // D
// 其实,我们可以跳过 ():
new D().logger(); // D
// 并且它可以正常运行
2
3
4
5
6
7
8
9
10
11
12
即使在内置类中,括号也是可选的:
new Date().getDay();
new Date().getMonth();
new Date().getYear();
2
3
# 九、void
void 是 JS 中的关键字,用于评估语句并返回未定义。
class D {
logger() {
return 89;
}
}
const d = new D();
console.log(void d.logger()); // undefined
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
2
3
4
5
6
7
8
9
# 十一、一元运算符 +
一元 + 运算符将其操作数转换为数字类型。
+"23" + // 23
{} + // NaN
null + // 0
undefined + // NaN
{ valueOf: () => 67 } + // 67
"nnamdi45"; // NaN
2
3
4
5
6
当我们希望将变量快速转换为 Number 时,这非常方便。
# 十二、一元运算符 -
一元运算符 - 将其操作数转换为 Number 类型,然后取反。
该运算符将一元 + 运算符的结果取反。首先,它将操作数转换为其 Number 值,然后取反该值。
-"23"; // -23
-{} // NaN
-null // -0
-undefined // NaN
-{ valueOf: () => 67 } // -67
-"nnamdi45" // NaN
2
3
4
5
如果转换为数值的结果为 NaN ,则不会应用取反。
取负 +0 产生 -0 ,取负 -0 产生 +0 。
- +0 // -0
- -0 // 0
2
# 十三、指数运算符 **
我们可以使用 ** 运算符在 JS 中进行相同的操作:
2 ** 3 // 8
9 ** 3 // 729
2