前言
本文是对阅读阮一峰老师的 <<ES6标准入门>>中 Math对象,作用域,Object.is() 知识点进行梳理
一. Math对象
- Math.trunc()
Math.trunc 方法用于去除一个数的小数部分,返回整数部分。
对于非数值, Math.trunc 内部使用 Number 方法将其先转为数值。
Math.trunc(4.1) // 4
Math.trunc(4.9) // 4
Math.trunc(-4.1) // -4
Math.trunc(-4.9) // -4
Math.trunc(-0.1234) // -0
代码模拟
Math.trunc = Math.trunc || function(x) {
return x < 0 ? Math.ceil(x) : Math.floor(x);
};
- Math.sign()
Math.sign 方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先
将其转换为数值。
它会返回五种值:
(1). 参数为正数,返回+1;
(2). 参数为负数,返回-1;
(3). 参数为0,返回0;
(4). 参数为-0,返回-0;
(5). 其他值,返回NaN。
Math.sign = Math.sign || function(x) {
x = +x; // convert to a number
if (x === 0 || isNaN(x)) {
return x;
}
return x > 0 ? 1 : -1;
};
二. 函数作用域与形参默认赋值
一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域
(context)。等到初始化结束,这个作用域就会消失。这种语法行为,在不设置参
数默认值时,是不会出现的。
var x = 1;
function foo(y = x) {
console.log(y,'y');
}
foo() // 1, 'y
上面代码中,参数 y 的默认值等于变量 x 。调用函数 f 时,参数形成一个单独
的作用域。在这个作用域里面,默认值变量指向全局变量 x ,所以输出是 1。
注意: 参数参数形成一个单独的作用域先看函数本身有无赋值,再去看全局变量
像下面这种,因为都不能给形参正常赋默认值
var x = 1;
function foo(x) {
console.log(x,'x');
}
foo() // undefined, 'x'
或者
var x = 1;
function foo(x = x) {
console.log(x,'x');
}
foo()
/** Uncaught ReferenceError: Cannot access 'x' before initialization
at f (<anonymous>:2:16)
at <anonymous>:5:1 */
参数形成的作用域
比较以下两种情况
(1)
var x = 1;
function f(y = x) {
x = 2
console.log(x,y); // 2,1
}
f()
console.log(x) // 2
(2)
var x = 1;
function f(x,y = x) {
x = 2
console.log(x,y); // 2,undefined
}
f()
console.log(x) // 1
因为第二种情况,函数f一个参数赋值的是 f(),赋值的是undefined,所以并未和全局变量x建立联系;
第一种情况,则参数形成的作用域赋值时,y使用的是全局变量的x值,所以函数作用域中x的改变会影响到全局变量,但是如果是函数作用域新建的一个新的变量,则关联也因此断裂
var x = 1;
function f(y = x) {
var x = 2
console.log(x,y); // 2,1
}
f()
console.log(x) // 1
同样地,如果参数形成的作用域里面有函数,则该函数所在的作用域也是属于参数所形成的作用域范畴的
var x = 1;
function foo(x, y = function() { x = 2; }) {
x = 3;
y();
console.log(x); // 2
}
foo()
x // 1
三. Object.is()
ES5 比较两个值是否相等,只有两个运算符:相等运算符( == )和严格相等运算
符( === )。它们都有缺点,前者会自动转换数据类型,后者的 NaN 不等于自
身,以及 +0 等于 -0 。JavaScript 缺乏一种运算,在所有环境中,只要两个值是
一样的,它们就应该相等。
ES6 提出“Same-value equality”(同值相等)算法,用来解决这个问
题。
Object.is 就是部署这个算法的新方法。它用来比较两个值是否严格相等,
与严格比较运算符(===)的行为基本一致。
不同之处只有两个:一是 +0 不等于 -0 ,二是 NaN 等于自身。
+0 === -0 //true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
代码模拟
if (!Object.is) {
Object.defineProperty(Object, "is", {
value: function (x, y) {
// SameValue algorithm
if (x === y) {
// 处理+0 和 -0 的情况,核心是利用Infinity不等于-Infinity
return x !== 0 || 1 / x === 1 / y;
} else {
// 处理NaN和NaN的场景
return x !== x && y !== y;
}
}
});
}