现代JavaScript 之JavaScript 基础知识(第一部分 第二章) 易错总结

在这里插入图片描述

(现代JavaScript 之JavaScript 基础知识 第一部分 第二章 易错总结)

2.1 Hello, world!

1. 现代 JavaScript 中已经不这样使用了。这些注释是用于不支持 <script> 标签的古老的浏览器隐藏 JavaScript 代码的。由于最近 15 年内发布的浏览器都没有这样的问题,因此这种注释能帮你辨认出一些老掉牙的代码。

 <script type=…> <script language=…>

2. 一个单独的 &lt;script&gt;标签不能同时有 src 特性和内部包裹的代码。

<script src="file.js">
  alert(1); // 此内容会被忽略,因为设定了 src
</script>

2.2 代码结构

1. 在大多数的编辑器中,一行代码可以使用<kbd>Ctrl+/</kbd> 热键进行单行注释,<kbd> Ctrl+Shift+/ </kbd>的热键可以进行多行注释
2. 不要在 /*...*/ 内嵌套另一个 /*...*/

2.3 现代模式,"use strict"

1. 没有办法取消 "use strict"没有类似于 "no use strict" 这样的指令可以使程序返回默认模式。一旦进入了严格模式,就没有回头路了。
2. 当你使用 开发者控制台 运行代码时,请注意它默认是不启动 "use strict" 的。你可以尝试搭配使用 <kbd>Shift+Enter</kbd> 按键去输入多行代码,然后将 "use strict" 放在代码最顶部。
3. 目前我们欢迎将 "use strict"; 写在脚本的顶部。稍后,当你的代码全都写在了 class 和 module 中时,你则可以将 "use strict"; 这行代码省略掉。

2.4 变量

1. var 关键字与 let 大体 相同,也用来声明变量,但稍微有些不同,也有点“老派”。
2. 额外声明一个变量绝对是利大于弊的。现代的 JavaScript 压缩器和浏览器都能够很好地对代码进行优化,所以不会产生性能问题。为不同的值使用不同的变量可以帮助引擎对代码进行优化。

2.5 数据类型

8 种基本的数据类型

  • Number 类型
    特殊数值:Infinity-InfinityNaN,数学运算是安全的
  • BigInt 类型
    “number” 类型无法表示大于 (253-1)(即 9007199254740991),或小于 -(253-1) 的整数。这是其内部表示形式导致的技术限制。可以通过将 n 附加到整数字段的末尾来创建 BigInt 值。
  • String 类型
    反引号:let phrase = ``can embed another ${str}``;
  • Boolean 类型(逻辑类型)
    用于 true 和 false。
  • “null” 值
    JavaScript 中的 null 仅仅是一个代表“无”、“空”或“值未知”的特殊值。
  • “undefined” 值
    undefined 的含义是 未被赋值。如果一个变量已被声明,但未被赋值,那么它的值就是 undefined
  • object 类型
    用于更复杂的数据结构。
  • symbol 类型
    用于唯一的标识符。

typeof 运算符

  • 两种形式:typeof x 或者 typeof(x)。
  • typeof null 会返回 "object" —— 这是 JavaScript 编程语言的一个错误,实际上它并不是一个 object。

2.6 交互:alert、prompt 和 confirm

alert

alert("Hello");

弹出的带有信息的小窗口被称为 模态窗
prompt

result = prompt(title, [default]);
    title 显示给用户的文本
    default 可选的第二个参数,指定 input 框的初始值。(不是必须的)

confirm

result = confirm(question);

点击确定返回 true,点击取消返回 false

2.7 类型转换

字符串转换

字符串转换最明显。false 变成 "false",null 变成 "null" 等。
数字型转换

变成……
undefined NaN
null 0
true 和 false 1 and 0
string 去掉首尾空格后的纯数字字符串中含有的数字。如果剩余字符串为空,则转换结果为 0。否则,将会从剩余字符串中“读取”数字。当类型转换出现 error 时返回 NaN。

请注意 nullundefined 在这有点不同:null 变成数字 0undefined 变成 NaN
布尔型转换
转换规则如下:

  • 直观上为“空”的值(如 0、空字符串、null、undefined 和 NaN)将变为 false。
  • 其他值变成 true。
  • 对 "0" 和只有空格的字符串(比如:" ")进行布尔型转换时,输出结果为 true。

请注意:包含 0 的字符串 "0" 是 true

2.8 基础运算符,数学

数字转化,一元运算符 +

但是如果运算元不是数字,加号 + 则会将其转化为数字。

// 转化非数字
alert( +true ); // 1
alert( +"" );   // 0

2.9 值的比较

一个有趣的现象

let a = 0;
alert( Boolean(a) ); // false

let b = "0";
alert( Boolean(b) ); // true

alert(a == b); // true!

对 null 和 undefined 进行比较

当使用严格相等 === 比较二者时

它们不相等,因为它们属于不同的类型。

alert( null === undefined ); // false

当使用非严格相等 == 比较二者时

JavaScript 存在一个特殊的规则,会判定它们相等。它们俩就像“一对恋人”,仅仅等于对方而不等于其他任何的值(只在非严格相等下成立)。

alert( null == undefined ); // true

当使用数学式或其他比较方法 < > <= >= 时:

null/undefined 会被转化为数字:null 被转化为 0,undefined 被转化为 NaN。

alert( null > 0 );  // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) true

特立独行的 undefined

alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)

值的比较练习题

5 > 4 → true
"apple" > "pineapple" → false
"2" > "12" → true
undefined == null → true
undefined === null → false
null == "\n0\n" → false
null === +"\n0\n" → false

2.11 逻辑运算符

||(或)

result = value1 || value2 || value3;

一个或运算 || 的链,将返回第一个真值,如果不存在真值,就返回该链的最后一个值。

&&(与)

result = value1 && value2 && value3;

与运算返回第一个假值,如果没有假值就返回最后一个值。
与运算 && 的优先级比或运算 || 要高。

!(非)

两个非运算 !! 有时候用来将某个值转化为布尔类型:

alert( !!"non-empty string" ); // true
alert( !!null ); // false

下面的代码将会输出什么?

alert( alert(1) || 2 || alert(3) );

答案:首先是 1,然后是 2.

与运算连接的 alerts 的结果是什么?

alert( alert(1) && alert(2) );

答案:1,然后 undefined。

或运算、与运算、或运算串联的结果

alert( null || 2 && 3 || 4 );

答案:3。

2.12 空值合并运算符 '??'

a ?? b 的结果是:

  • 如果 a 是已定义的,则结果为 a,
  • 如果 a 不是已定义的,则结果为 b。

重写 result = a ?? b

result = (a !== null && a !== undefined) ? a : b;

举例


let firstName = null;
let lastName = null;
let nickName = "Supercoder";

// 显示第一个已定义的值:
alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder

与 || 比较

它们之间重要的区别是:

  • || 返回第一个 值。
  • ?? 返回第一个 已定义的 值。

如果没有明确添加括号,不能将其与 || 或 && 一起使用。

2.13 循环:while 和 for

普通 break 只会打破内部循环
标签 是在循环之前带有冒号的标识符:

outer: for (let i = 0; i < 3; i++) {
  for (let j = 0; j < 3; j++) {
    let input = prompt(`Value at coords (${i},${j})`, '');
    // 如果是空字符串或被取消,则中断并跳出这两个循环。
    if (!input) break outer; // (*)
    // 用得到的值做些事……
  }
}

我们还可以将标签移至单独一行:

outer:
for (let i = 0; i < 3; i++) { ... }

continue 指令也可以与标签一起使用。在这种情况下,执行跳转到标记循环的下一次迭代。

只有在循环内部才能调用 break/continue,并且标签必须位于指令上方的某个位置。

break label;  // 无法跳转到这个标签
label: for (...)

易错题
以下两个循环的 alert 值是否相同?

前缀形式 ++i: 从 1 到 4

let i = 0;
while (++i < 5) alert( i );

后缀形式 i++:从 1 到 5

let i = 0;
while (i++ < 5) alert( i );

2.14 "switch" 语句

共享同一段代码的几个 case 分支可以被分为一组:

let a = 3;
switch (a) {
  case 4:
    alert('Right!');
    break;

  case 3: // (*) 下面这两个 case 被分在一组
  case 5:
    alert('Wrong!');
    alert("Why don't you take a math class?");
    break;

  default:
    alert('The result is strange. Really.');
}

2.15 函数

默认值

如果未提供参数,那么其默认值则是 undefined。

如果我们想在本示例中设定“默认”的 text,那么我们可以在 = 之后指定它:

function showMessage(from, text = "no text given") {
  alert( from + ": " + text );
}
showMessage("Ann"); // Ann: no text given

这里 "no text given" 是一个字符串,但它可以是更复杂的表达式,并且只会在缺少参数时才会被计算和分配。所以,这也是可能的:

function showMessage(from, text = anotherFunction()) {
  // anotherFunction() 仅在没有给定 text 时执行
  // 其运行结果将成为 text 的值
}

后备的默认参数
我们可以拿它跟 undefined 做比较:

function showMessage(text) {
  if (text === undefined) {
    text = 'empty message';
  }
  alert(text);
}
showMessage(); // empty message

我们可以使用 || 运算符:

// 如果 "text" 参数被省略或者被传入空字符串,则赋值为 'empty'
function showMessage(text) {
  text = text || 'empty';
  ...
}

现代 JavaScript 引擎支持 空值合并运算符 ??,当可能遇到其他假值时它更有优势,如 0 会被视为正常值不被合并:


// 如果没有传入 "count" 参数,则显示 "unknown"
function showCount(count) {
  alert(count ?? "unknown");
}

showCount(0); // 0
showCount(null); // unknown
showCount(); // unknown

空值的 return 或没有 return 的函数返回值为 undefined

函数命名

函数以 XX 开始……

  • "get…" —— 返回一个值,
  • "calc…" —— 计算某些内容,
  • "create…" —— 创建某些内容,
  • "check…" —— 检查某些内容并返回 boolean 值,等。

2.16 函数表达式

在 JavaScript 中,函数不是“神奇的语言结构”,而是一种特殊的值。

函数声明:

function sayHi() {
  alert( "Hello" );
}

函数表达式:

let sayHi = function() {
  alert( "Hello" );
};

我们可以复制函数到其他变量:

function sayHi() {   // (1) 创建
  alert( "Hello" );
}

let func = sayHi;    // (2) 复制

func(); // Hello     // (3) 运行复制的值(正常运行)!
sayHi(); // Hello    //     这里也能运行(为什么不行呢)

为什么这里末尾会有个分号?

function sayHi() {
  // ...
}
let sayHi = function() {
  // ...
};
  • 在代码块的结尾不需要加分号 ;,像 if { ... },for { },function f { } 等语法结构后面都不用加。
  • 函数表达式是在语句内部的:let sayHi = ...;,作为一个值。它不是代码块而是一个赋值语句。不管值是什么,都建议在语句末尾添加分号 ;。所以这里的分号与函数表达式本身没有任何关系,它只是用于终止语句。

回调函数

function ask(question, yes, no) {
  if (confirm(question)) yes()
  else no();
}

function showOk() {
  alert( "You agreed." );
}

function showCancel() {
  alert( "You canceled the execution." );
}

// 用法:函数 showOk 和 showCancel 被作为参数传入到 ask
ask("Do you agree?", showOk, showCancel);

ask 的两个参数值 showOk 和 showCancel 可以被称为 回调函数 或简称 回调。

函数表达式 vs 函数声明

函数表达式是在代码执行到达时被创建,并且仅从那一刻起可用。

一旦代码执行到赋值表达式 let sum = function… 的右侧,此时就会开始创建该函数,并且可以从现在开始使用(分配,调用等)。

函数声明则不同。

在函数声明被定义之前,它就可以被调用。

一个全局函数声明对整个脚本来说都是可见的,无论它被写在这个脚本的哪个位置。

函数声明的另外一个特殊的功能是它们的块级作用域。

严格模式下,当一个函数声明在一个代码块内时,它在该代码块内的任何位置都是可见的。但在代码块外不可见。

如果我们使用函数声明,则以下代码无法像预期那样工作:

let age = prompt("What is your age?", 18);
// 有条件地声明一个函数
if (age < 18) {
  function welcome() {
    alert("Hello!");
  }
} else {
  function welcome() {
    alert("Greetings!");
  }
}
// ……稍后使用
welcome(); // Error: welcome is not defined

正确的做法是使用函数表达式,并将 welcome 赋值给在 if 外声明的变量,并具有正确的可见性。

下面的代码可以如愿运行:

let age = prompt("What is your age?", 18);
let welcome;
if (age < 18) {
  welcome = function() {
    alert("Hello!");
  };
} else {
  welcome = function() {
    alert("Greetings!");
  };
}
welcome(); // 现在可以了

2.17 箭头函数,基础知识

单行箭头函数

let func = (arg1, arg2, ...argN) => expression

多行的箭头函数

let sum = (a, b) => {  // 花括号表示开始一个多行函数
  let result = a + b;
  return result; // 如果我们使用了花括号,那么我们需要一个显式的 “return”
};
alert( sum(1, 2) ); // 3

2.18 JavaScript 特性

typeof 运算符返回值的类型,但有两个例外:

    typeof null == "object" // JavaScript 编程语言的设计错误
    typeof function(){} == "function" // 函数被特殊对待

值 null 和 undefined 是特殊的:它们只在 == 下相等,且不相等于其他任何值。

猜你喜欢

转载自blog.51cto.com/15056944/2564140