语法与数据类型
语法
var\let\const
var
声明一个变量,可选初始化一个值。
let
声明一个块作用域的局部变量,可选初始化一个值。
const
声明一个块作用域的只读常量。
用 var
或 let
语句声明的变量,如果没有赋初始值,则其值为 undefined。如果访问一个未声明的变量会导致抛出 ReferenceError 异常:
undefined
值在布尔类型环境中会被当作false
- 数值类型环境中
undefined
值会被转换为NaN
- 当你对一个 null 变量求值时,空值
null
在数值类型环境中会被当作 0 来对待
变量提升
一个函数中所有的
var
语句应尽可能地放在接近函数顶部的地方。
- JavaScript 变量的另一个不同寻常的地方是,你可以先使用变量稍后再声明变量而不会引发异常。这一概念称为变量提升;JavaScript 变量感觉上是被“提升”或移到了函数或语句的最前面。但是,提升后的变量将返回 undefined 值。因此在使用或引用某个变量之后进行声明和初始化操作,这个被提升的变量仍将返回 undefined 值。
- 在 ECMAScript 6 中,
let
和const
同样会被提升变量到代码块的顶部但是不会被赋予初始值。在变量声明之前引用这个变量,将抛出引用错误(ReferenceError)。这个变量将从代码块一开始的时候就处在一个“暂时性死区”,直到这个变量被声明为止。- 对于函数来说,只有函数声明会被提升到顶部,而函数表达式不会被提升。
/*** 例子 2*/ // will return a value of undefined var myvar = "my value";(function () {console.log(myvar); // undefinedvar myvar = "local value"; })(); ------------------------------------------------------- console.log(x); // ReferenceError let x = 3; ---------------------------------------------------------- /* 函数声明 */foo(); // "bar"function foo() {console.log("bar"); }/* 函数表达式 */baz(); // 类型错误:baz 不是一个函数var baz = function () {console.log("bar2"); };
常量
对象属性被赋值为常量是不受保护的,所以下面的语句执行时不会产生错误。
const MY_OBJECT = { key: "value" };
MY_OBJECT.key = "otherValue";
同样的,数组的被定义为常量也是不受保护的,所以下面的语句执行时也不会产生错误。
const MY_ARRAY = ["HTML", "CSS"];
MY_ARRAY.push("JAVASCRIPT");
console.log(MY_ARRAY); //logs ['HTML','CSS','JAVASCRIPT'];
全局变量
实际上,全局变量是全局对象的属性。在网页中,(译注:缺省的)全局对象是 window ,所以你可以用形如
window.
variable
的语法来设置和访问全局变量。常量
数据类型
- 七种基本数据类型:
- 布尔值(Boolean),有 2 个值分别是:
true
和false
。- null,一个表明 null 值的特殊关键字。JavaScript 是大小写敏感的,因此
null
与Null
、NULL
或变体完全不同。- undefined,和 null 一样是一个特殊的关键字undefined 表示变量未赋值时的属性。
- 数字(Number),整数或浮点数,例如:
42
或者3.14159
。- 任意精度的整数(BigInt),可以安全地存储和操作大整数,甚至可以超过数字的安全整数限制。
- 字符串(String),字符串是一串表示文本值的字符序列,例如:
"Howdy"
。- 代表(Symbol,在 ECMAScript 6 中新添加的类型)。一种实例是唯一且不可改变的数据类型。
- 以及对象(Object)。
对象属性名字可以是任意字符串,包括空串。如果对象属性名字不是合法的 javascript 标识符,它必须用引号包裹。
const unusualPropertyNames = {'': '空字符串','!': '砰!' } console.log(unusualPropertyNames.''); // SyntaxError: Unexpected string console.log(unusualPropertyNames.!); // SyntaxError: Unexpected token ! ----------------------------------------------------------------------- console.log(unusualPropertyNames[""]); // 空字符串 console.log(unusualPropertyNames["!"]); // 砰!
!!!核心基础:1.访问对象属性foo['var']最稳妥 2.字符串插值"${var}"
//访问对象属性 var foo = { a: "alpha", 2: "two" }; console.log(foo.a); // alpha console.log(foo[2]); // two //console.log(foo.2); // SyntaxError: missing ) after argument list //console.log(foo[a]); // ReferenceError: a is not defined console.log(foo["a"]); // alpha console.log(foo["2"]); // two ---------------------------------------------------------------------------- //字符串插值"${var}" var name = "Bob",time = "today"; `Hello ${name}, how are you ${time}?`;
数字-》字符串:“+”
x = "The answer is " + 42; // "The answer is 42" y = 42 + " is the answer"; // "42 is the answer"
字符串-》数字:parseInt()、parseFloat()
parseInt
方法只能返回整数,所以使用它会丢失小数部分。另外,调用 parseInt 时最好总是带上进制(radix)参数,这个参数用于指定使用哪一种进制。x = "The answer is " + 42; // "The answer is 42" y = 42 + " is the answer"; // "42 is the answer"
进制
整数可以用十进制(基数为 10)、十六进制(基数为 16)、八进制(基数为 8)以及二进制(基数为 2)表示。
- 十进制整数字面量由一串数字序列组成,且没有前缀 0。
- 八进制的整数以 0(或 0O、0o)开头,只能包括数字 0-7。
- 十六进制整数以 0x(或 0X)开头,可以包含数字(0-9)和字母 a~f 或 A~F。
- 二进制整数以 0b(或 0B)开头,只能包含数字 0 和 1。
控制语句与错误处理
throw语句
throw "Error2"; // String type
throw 42; // Number type
throw true; // Boolean type
throw {toString: function () {return "I'm an object!";},
};
------------------------------------------
//可以在抛出异常时声明一个对象。那你就可以在 catch 块中查询到对象的属性。// Create an object type UserException
function UserException(message) {this.message = message;this.name = "UserException";
}// Make the exception convert to a pretty string when used as
// a string (e.g. by the error console)
UserException.prototype.toString = function () {return this.name + ': "' + this.message + '"';
};// Create an instance of the object type and throw it
throw new UserException("Value too high");
try....catch...finally
换句话说,如果你在 try 代码块中的代码如果没有执行成功,那么你希望将执行流程转入 catch 代码块。如果 try 代码块没有抛出异常,catch 代码块就会被跳过。
finally
块无论是否抛出异常都会执行。如果抛出了一个异常,就算没有异常处理,finally
块里的语句也会执行。
执行顺序
function f() {try {console.log(0);throw "bogus";} catch (e) {console.log(1);return true; // this return statement is suspended// until finally block has completedconsole.log(2); // not reachable} finally {console.log(3);return false; // overwrites the previous "return"console.log(4); // not reachable}// "return false" is executed nowconsole.log(5); // not reachable
}
f(); // console 0, 1, 3; returns false
----------------------------------------------------------------------
function f() {try {throw "bogus";} catch (e) {console.log('caught inner "bogus"');throw e; // this throw statement is suspended until// finally block has completed} finally {return false; // overwrites the previous "throw"}// "return false" is executed now
}try {f();
} catch (e) {// this is never reached because the throw inside// the catch is overwritten// by the return in finallyconsole.log('caught outer "bogus"');
}// OUTPUT
// caught inner "bogus"
Error对象
DOMException、ECMAScript exceptions
function doSomethingErrorProne () {if (ourCodeMakesAMistake()) {throw (new Error('The message'));} else {doSomethingToGetAJavascriptError();}
}
....
try {doSomethingErrorProne();
}
catch (e) {console.log(e.name); // logs 'Error'console.log(e.message); // logs 'The message' or a JavaScript error message)
}
循环与迭代
基本循环语句
//for语句
for (var i = 0; i < selectObject.options.length; i++) {if (selectObject.options[i].selected) {numberSelected++;}}
---------------------------------------------------------
//do...while语句
var i = 0;
do {i += 1;console.log(i);
} while (i < 5);
----------------------------------------------------------
//while语句
var n = 0;
var x = 0;
while (n < 3) {n++;x += n;
}
------------------------------------------------------------
break与continue
label语句
一个 label 提供了一个让你在程序中其他位置引用它的标识符。例如,你可以用 label 标识一个循环,然后使用
break
或者continue
来指出程序是否该停止循环还是继续循环。var num = 0; outPoint: for (var i = 0; i < 10; i++) {for (var j = 0; j < 10; j++) {if (i == 5 && j == 5) {break outPoint; // 在 i = 5,j = 5 时,跳出所有循环,// 返回到整个 outPoint 下方,继续执行}num++;} }alert(num); // 输出 55
var num = 0; outPoint: for (var i = 0; i < 10; i++) {for (var j = 0; j < 10; j++) {if (i == 5 && j == 5) {continue outPoint;}num++;} } alert(num); // 95
for...in语句
for...in 语句循环一个指定的变量来循环一个对象所有可枚举的属性。JavaScript 会为每一个不同的属性执行指定的语句。
虽然使用 for...in 来迭代数组 Array 元素听起来很诱人,但是它返回的东西除了数字索引外,还有可能是你自定义的属性名字。因此还是用带有数字索引的传统的 for 循环来迭代一个数组比较好,因为,如果你想改变数组对象,比如添加属性或者方法,for...in 语句迭代的是自定义的属性,而不是数组的元素。
function dump_props(obj, obj_name) {var result = "";for (var i in obj) {result += obj_name + "." + i + " = " + obj[i] + "<br>";}result += "<hr>";return result; }
for...of语句
for...of 语句在可迭代对象(包括Array、Map、Set、arguments 等等)上创建了一个循环,对值的每一个独特属性调用一次迭代。
迭代协议: 迭代协议具体分为两个协议:可迭代协议和迭代器协议。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Iteration_protocols
let arr = [3, 5, 7]; arr.foo = "hello";for (let i in arr) {console.log(i); // 输出 "0", "1", "2", "foo" }for (let i of arr) {console.log(i); // 输出 "3", "5", "7" }// 注意 for...of 的输出没有出现 "hello"