变量没有类型,但它们持有的值有类型。类型定义了值的行为特征。
字符串不可变是指字符串的成员函数不会改变其原始值,而是创建并返回一个新的字符 串。而数组的成员函数都是在其原始值上进行操作。
-
NaN 是一个“警戒值”(sentinel value,有特殊用途的常规值),用于指出数字类型中的错误 情况,即“执行数学运算没有成功,这是失败后返回的结果” (NaN 是一个特殊值,它和自身不相等,是唯一一个非自反(自反,reflexive,即 x === x 不 成立)的值。而 NaN != NaN 为 true)
// JavaScript 中的引用和其他语言中的引用 / 指针不同,它们不能指向别的变量 / 引用,只能指向值。
function foo(x) {
x.push( 4 );
x;
// 然后
x = [4,5,6];
x.push( 7 );
x;
}
var a = [1,2,3];
foo( a );
a; // a现在输出啥
拆封
如果想要得到封装对象中的基本类型值,可以使用 valueOf() 函数:
var a = new String( "abc" );
var b = new Number( 42 );
var c = new Boolean( true );
a.valueOf(); // "abc"
b.valueOf(); // 42
c.valueOf(); // true
构造函数 Function 只在极少数情况下很有用,比如动态定义函数参数和函数体的时候。
类型转换发生在静态类型语言的编译阶段,而强制类型转换则发生在动态类型语言的运行时(runtime)。
最好还是使用 ES5 中新加入的静态方法 Date.now() 代替 new Date().getTime(); 使 用 new Date(..).getTime() 来获得指定时间的时间戳。
Symbol()
函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol
函数的返回值是不相等的。
// 没有参数的情况
let s1 = Symbol();
let s2 = Symbol();
s1 === s2 // false
// 有参数的情况
let s1 = Symbol('foo');
let s2 = Symbol('foo');
s1 === s2 // false
如果 < 比较的两个值都是字符串, 就像在 b < c 中那样,那么比较按照字典顺序(即字典中的字母表顺序)进行。如果其中 一边或两边都不是字符串,就像在 a < b 中那样,那么这两个值的类型都转换为数字,然 后进行普通的数字比较。
将闭包看作“记忆”并在函数运行完毕后继续访问这个函数作用域(其变量)的一 种方法。
生成器为 JavaScript 函数引入了一种新的执行模式,其中生成器可以暂停在 yield 点上, 并在之后被异步继续。暂停与继续的能力使得生成器中同步的、看似连续的代码可以在后 台异步执行。通过这种方式,我们解决了回调的非线性、非局部跳转引发的代码混乱问 题,因而让我们的异步代码看似同步,更容易追踪。
es6
和传统的 var 声明变量不同,不管出 现在什么位置,var 都是归属于包含它的整个函数作用域。let 声明归属于块作用域,但是 直到在块中出现才会被初始化。
var funcs = [];
for (let i = 0; i < 5; i++) {
funcs.push( function(){
console.log( i );
} );
}
funcs[3](); // 3
for 循环头部的 let i 不只为 for 循环本身声明了一个 i,而是为循环的每一次迭代都重新 声明了一个新的 i。这意味着 loop 迭代内部创建的闭包封闭的是每次迭代中的变量,就像 期望的那样。(const 可以用在 for、for..in 以及 for..of 循环的变量声明中(参见 2.9 节)。但如果想要 重新赋值就会抛出错误,比如 for 循环中常用的 i++。证明每循环一次就创建一个新的作用域) 如果试验同样的代码,只把 var i 放在 for 循环头部,得到的结果就会是 5 而不是 3,因 为在外层作用域中只有一个 i,这个 i 被封闭进去,而不是每个迭代的函数会封闭一个 新的 i。
const
常量不是对这个值本身的限制,而是对赋值的那个变量的限制。换句话说,这个值并没有 因为 const 被锁定或者不可变,只是赋值本身不可变。如果这个值是复杂值,比如对象或 者数组,其内容仍然是可以修改的。
{
const a = [1,2,3];
a.push( 4 );
console.log( a ); // [1,2,3,4]
a = 42; // TypeError!
}
变量 a 并不持有一个常量数组;相反地,它持有一个指向数组的常量引用。数组本身是可 以随意改变的。
var w = 1, z = 2;
function foo( x = w + 1, y = x + 1, z = z + 1 ) {
console.log( x, y, z );
}
foo(); // ReferenceError z没有初始化报错
var controller = {
makeRequest: (..) => {
// ..
this.helper(..); // this指向全局
},
helper: (..) => {
// ..
}
};
controller.makeRequest(..);
// 尽管我们以 controller.makeRequest(..) 的形式调用,this.helper 引用还是会失败,因为
这里的 this 并不像平常一样指向 controller。那么它指向哪里呢?它是从包围的作用域中
词法继承而来的 this。在前面的代码中也就是全局作用域,其中 this 指向那个全局对象。