diff --git a/.github/workflows/wangdoc.yml b/.github/workflows/wangdoc.yml
index 80f8bfe..c3e5cbe 100644
--- a/.github/workflows/wangdoc.yml
+++ b/.github/workflows/wangdoc.yml
@@ -10,28 +10,27 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
persist-credentials: false
- name: Setup Node.js
- uses: actions/setup-node@main
+ uses: actions/setup-node@v4
with:
- node-version: '14'
+ node-version: 'latest'
- name: Install dependencies
run: npm install
- name: Build pages
run: npm run build
- name: Deploy to website
- uses: JamesIves/github-pages-deploy-action@3.7.1
+ uses: JamesIves/github-pages-deploy-action@v4
with:
- GIT_CONFIG_NAME: wangdoc-bot
- GIT_CONFIG_EMAIL: yifeng.ruan@gmail.com
- REPOSITORY_NAME: wangdoc/website
- ACCESS_TOKEN: ${{ secrets.WANGDOC_BOT_TOKEN }}
- BASE_BRANCH: master
- BRANCH: master # The branch the action should deploy to.
- FOLDER: dist # The folder the action should deploy.
- TARGET_FOLDER: dist/javascript
- CLEAN: true # Automatically remove deleted files from the deploy branch
- COMMIT_MESSAGE: update from JavaScript tutorial
+ git-config-name: wangdoc-bot
+ git-config-email: yifeng.ruan@gmail.com
+ repository-name: wangdoc/website
+ token: ${{ secrets.WANGDOC_BOT_TOKEN }}
+ branch: master # The branch the action should deploy to.
+ folder: dist # The folder the action should deploy.
+ target-folder: dist/javascript
+ clean: true # Automatically remove deleted files from the deploy branch
+ commit-message: update from JavaScript tutorial
diff --git a/docs/async/general.md b/docs/async/general.md
index a4c9747..a745bfe 100644
--- a/docs/async/general.md
+++ b/docs/async/general.md
@@ -271,7 +271,7 @@ function launcher() {
running--;
if(items.length> 0) {
launcher();
- } else if(running == 0) {
+ } else if(running === 0) {
final(results);
}
});
diff --git a/docs/basic/grammar.md b/docs/basic/grammar.md
index b1ebde1..b0dea02 100644
--- a/docs/basic/grammar.md
+++ b/docs/basic/grammar.md
@@ -485,7 +485,7 @@ var msg = '数字' + n + '是' + (n % 2 === 0 ? '偶数' : '奇数');
### while 循环
-`While`语句包括一个循环条件和一段代码块,只要条件为真,就不断循环执行代码块。
+`while`语句包括一个循环条件和一段代码块,只要条件为真,就不断循环执行代码块。
```javascript
while (条件)
diff --git a/docs/bom/cookie.md b/docs/bom/cookie.md
index 80c542c..e0ae045 100644
--- a/docs/bom/cookie.md
+++ b/docs/bom/cookie.md
@@ -342,7 +342,7 @@ document.cookie = "foo=bar; expires=2020年12月31日 23:59:59 GMT";
各个属性的写入注意点如下。
- `path`属性必须为绝对路径,默认为当前路径。
-- `domain`属性值必须是当前发送 Cookie 的域名的一部分。比如,当前域名是`example.com`,就不能将其设为`foo.com`。该属性默认为当前的一级域名(不含二级域名)。
+- `domain`属性值必须是当前发送 Cookie 的域名的一部分。比如,当前域名是`example.com`,就不能将其设为`foo.com`。该属性默认为当前的一级域名(不含二级域名)。如果显式设置该属性,则该域名的任意子域名也可以读取 Cookie。
- `max-age`属性的值为秒数。
- `expires`属性的值为 UTC 格式,可以使用`Date.prototype.toUTCString()`进行日期格式转换。
@@ -352,9 +352,11 @@ document.cookie = "foo=bar; expires=2020年12月31日 23:59:59 GMT";
document.cookie = 'fontSize=14; '
+ 'expires=' + someDate.toGMTString() + '; '
+ 'path=/subdirectory; '
- + 'domain=*.example.com';
+ + 'domain=example.com';
```
+注意,上面的`domain`属性,以前的写法是`.example.com`,表示子域名也可以读取该 Cookie,新的写法可以省略前面的点。
+
Cookie 的属性一旦设置完成,就没有办法读取这些属性的值。
删除一个现存 Cookie 的唯一方法,是设置它的`expires`属性为一个过去的日期。
diff --git a/docs/bom/cors.md b/docs/bom/cors.md
index 23dfac9..566e1f0 100644
--- a/docs/bom/cors.md
+++ b/docs/bom/cors.md
@@ -1,12 +1,12 @@
# CORS 通信
-CORS 是一个 W3C 标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨域的服务器,发出`XMLHttpRequest`请求,从而克服了 AJAX 只能同源使用的限制。
+CORS 是一个 W3C 标准,全称是"跨源资源共享"(Cross-origin resource sharing),或者通俗地称为"跨域资源共享"。它允许浏览器向跨源的服务器,发出`XMLHttpRequest`请求,从而克服了 AJAX 只能同源使用的限制。
## 简介
CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能。
-整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与普通的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨域,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感知。因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨域通信。
+整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与普通的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感知。因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨源通信。
## 两种请求
@@ -30,7 +30,7 @@ CORS 请求分成两类:简单请求(simple request)和非简单请求(n
凡是不同时满足上面两个条件,就属于非简单请求。一句话,简单请求就是简单的 HTTP 方法与简单的 HTTP 头信息的结合。
-这样划分的原因是,表单在历史上一直可以跨域发出请求。简单请求就是表单请求,浏览器沿袭了传统的处理方式,不把行为复杂化,否则开发者可能转而使用表单,规避 CORS 的限制。对于非简单请求,浏览器会采用新的处理方式。
+这样划分的原因是,表单在历史上一直可以跨源发出请求。简单请求就是表单请求,浏览器沿袭了传统的处理方式,不把行为复杂化,否则开发者可能转而使用表单,规避 CORS 的限制。对于非简单请求,浏览器会采用新的处理方式。
## 简单请求
@@ -38,7 +38,7 @@ CORS 请求分成两类:简单请求(simple request)和非简单请求(n
对于简单请求,浏览器直接发出 CORS 请求。具体来说,就是在头信息之中,增加一个`Origin`字段。
-下面是一个例子,浏览器发现这次跨域 AJAX 请求是简单请求,就自动在头信息之中,添加一个`Origin`字段。
+下面是一个例子,浏览器发现这次跨源 AJAX 请求是简单请求,就自动在头信息之中,添加一个`Origin`字段。
```http
GET /cors HTTP/1.1
@@ -99,7 +99,7 @@ xhr.withCredentials = true;
xhr.withCredentials = false;
```
-需要注意的是,如果服务器要求浏览器发送 Cookie,`Access-Control-Allow-Origin`就不能设为星号,必须指定明确的、与请求网页一致的域名。同时,Cookie 依然遵循同源政策,只有用服务器域名设置的 Cookie 才会上传,其他域名的 Cookie 并不会上传,且(跨域)原网页代码中的`document.cookie`也无法读取服务器域名下的 Cookie。
+需要注意的是,如果服务器要求浏览器发送 Cookie,`Access-Control-Allow-Origin`就不能设为星号,必须指定明确的、与请求网页一致的域名。同时,Cookie 依然遵循同源政策,只有用服务器域名设置的 Cookie 才会上传,其他域名的 Cookie 并不会上传,且(跨源)原网页代码中的`document.cookie`也无法读取服务器域名下的 Cookie。
## 非简单请求
@@ -107,7 +107,7 @@ xhr.withCredentials = false;
非简单请求是那种对服务器提出特殊要求的请求,比如请求方法是`PUT`或`DELETE`,或者`Content-Type`字段的类型是`application/json`。
-非简单请求的 CORS 请求,会在正式通信之前,增加一次 HTTP 查询请求,称为"预检"请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些 HTTP 方法和头信息字段。只有得到肯定答复,浏览器才会发出正式的`XMLHttpRequest`请求,否则就报错。这是为了防止这些新增的请求,对传统的没有 CORS 支持的服务器形成压力,给服务器一个提前拒绝的机会,这样可以防止服务器收到大量`DELETE`和`PUT`请求,这些传统的表单不可能跨域发出的请求。
+非简单请求的 CORS 请求,会在正式通信之前,增加一次 HTTP 查询请求,称为"预检"请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些 HTTP 方法和头信息字段。只有得到肯定答复,浏览器才会发出正式的`XMLHttpRequest`请求,否则就报错。这是为了防止这些新增的请求,对传统的没有 CORS 支持的服务器形成压力,给服务器一个提前拒绝的机会,这样可以防止服务器收到大量`DELETE`和`PUT`请求,这些传统的表单不可能跨源发出的请求。
下面是一段浏览器的 JavaScript 脚本。
@@ -199,7 +199,7 @@ Access-Control-Max-Age: 1728000
**(1)`Access-Control-Allow-Methods`**
-该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。
+该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨源请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。
**(2)`Access-Control-Allow-Headers`**
diff --git a/docs/bom/same-origin.md b/docs/bom/same-origin.md
index 50577ce..4a11a0b 100644
--- a/docs/bom/same-origin.md
+++ b/docs/bom/same-origin.md
@@ -194,7 +194,7 @@ window.addEventListener('message', function (e) {
`message`事件的参数是事件对象`event`,提供以下三个属性。
> - `event.source`:发送消息的窗口
-> - `event.origin`: 消息发向的网址
+> - `event.origin`: 消息发送者的源(origin),即协议、域名、端口。
> - `event.data`: 消息内容
下面的例子是,子窗口通过`event.source`属性引用父窗口,然后发送消息。
@@ -208,7 +208,7 @@ function receiveMessage(event) {
上面代码有几个地方需要注意。首先,`receiveMessage`函数里面没有过滤信息的来源,任意网址发来的信息都会被处理。其次,`postMessage`方法中指定的目标窗口的网址是一个星号,表示该信息可以向任意网址发送。通常来说,这两种做法是不推荐的,因为不够安全,可能会被恶意利用。
-`event.origin`属性可以过滤不是发给本窗口的消息。
+`event.origin`属性可以过滤非许可地址发来的消息。
```javascript
window.addEventListener('message', receiveMessage);
diff --git a/docs/bom/window.md b/docs/bom/window.md
index a012d61..a873fae 100644
--- a/docs/bom/window.md
+++ b/docs/bom/window.md
@@ -579,7 +579,7 @@ var start = null;
function step(timestamp) {
if (!start) start = timestamp;
var progress = timestamp - start;
- // 元素不断向左移,最大不超过200像素
+ // 元素不断向右移,最大不超过200像素
element.style.left = Math.min(progress / 10, 200) + 'px';
// 如果距离第一次执行不超过 2000 毫秒,
// 就继续执行动画
diff --git a/docs/dom/css.md b/docs/dom/css.md
index 5a1d39a..b4f1a2d 100644
--- a/docs/dom/css.md
+++ b/docs/dom/css.md
@@ -292,7 +292,7 @@ CSS.supports('display: table-cell;') // false
行内样式(inline style)具有最高的优先级,改变行内样式,通常会立即反映出来。但是,网页元素最终的样式是综合各种规则计算出来的。因此,如果想得到元素实际的样式,只读取行内样式是不够的,需要得到浏览器最终计算出来的样式规则。
-`window.getComputedStyle`方法,就用来返回浏览器计算后得到的最终规则。它接受一个节点对象作为参数,返回一个 CSSStyleDeclaration 实例,包含了指定节点的最终样式信息。所谓"最终样式信息",指的是各种 CSS 规则叠加后的结果。
+`window.getComputedStyle()`方法,就用来返回浏览器计算后得到的最终规则。它接受一个节点对象作为参数,返回一个 CSSStyleDeclaration 实例,包含了指定节点的最终样式信息。所谓"最终样式信息",指的是各种 CSS 规则叠加后的结果。
```javascript
var div = document.querySelector('div');
@@ -328,7 +328,7 @@ var height = styleObj.getPropertyValue('height');
- CSSStyleDeclaration 实例返回的 CSS 值都是绝对单位。比如,长度都是像素单位(返回值包括`px`后缀),颜色是`rgb(#, #, #)`或`rgba(#, #, #, #)`格式。
- CSS 规则的简写形式无效。比如,想读取`margin`属性的值,不能直接读,只能读`marginLeft`、`marginTop`等属性;再比如,`font`属性也是不能直接读的,只能读`font-size`等单个属性。
- 如果读取 CSS 原始的属性名,要用方括号运算符,比如`styleObj['z-index']`;如果读取骆驼拼写法的 CSS 属性名,可以直接读取`styleObj.zIndex`。
-- 该方法返回的 CSSStyleDeclaration 实例的`cssText`属性无效,返回`undefined`。
+- 该方法返回的 CSSStyleDeclaration 实例的`cssText`属性总是返回空字符串。
## CSS 伪元素
@@ -401,9 +401,9 @@ myStyleSheet instanceof StyleSheet // true
注意,`disabled`属性只能在 JavaScript 脚本中设置,不能在 HTML 语句中设置。
-**(2)Stylesheet.href**
+**(2)StyleSheet.href**
-`Stylesheet.href`返回样式表的网址。对于内嵌样式表,该属性返回`null`。该属性只读。
+`StyleSheet.href`返回样式表的网址。对于内嵌样式表,该属性返回`null`。该属性只读。
```javascript
document.styleSheets[0].href
diff --git a/docs/dom/document.md b/docs/dom/document.md
index 3eb1d02..7af7f3a 100644
--- a/docs/dom/document.md
+++ b/docs/dom/document.md
@@ -69,7 +69,10 @@ document.scrollingElement.scrollTop = 0;
`document.fullscreenElement`属性返回当前以全屏状态展示的 DOM 元素。如果不是全屏状态,该属性返回`null`。
```javascript
-if (document.fullscreenElement.nodeName == 'VIDEO') {
+if (
+ document.fullscreenElement &&
+ document.fullscreenElement.nodeName == 'VIDEO'
+) {
console.log('全屏播放视频');
}
```
@@ -363,7 +366,7 @@ document.replaceChild(
);
```
-上面代码中,第一步生成一个新的 HTML 文档`doc`,然后用它的根元素`document.documentElement`替换掉`document.documentElement`。这会使得当前文档的内容全部消失,变成`hello world`。
+上面代码中,第一步生成一个新的 HTML 文档`doc`,然后用它的根元素`doc.documentElement`替换掉`document.documentElement`。这会使得当前文档的内容全部消失,变成`hello world`。
## 方法
@@ -716,7 +719,7 @@ var element = document.getElementById('ul');
element.appendChild(docfrag);
```
-上面代码中,文档片断`docfrag`包含四个`
`节点,这些子节点被一次性插入了当前文档。
+上面代码中,文档片段`docfrag`包含四个``节点,这些子节点被一次性插入了当前文档。
### document.createEvent()
diff --git a/docs/dom/element.md b/docs/dom/element.md
index 2b5ea6d..6a73887 100644
--- a/docs/dom/element.md
+++ b/docs/dom/element.md
@@ -371,8 +371,8 @@ document.body.scrollHeight
```javascript
// HTML 代码如下
-// ...
-document.getElementById('myDiv').scrollHeight // 356
+//
...
+document.getElementById('myDiv').scrollHeight // 200
```
上面代码中,即使`myDiv`元素的 CSS 高度只有200像素,且溢出部分不可见,但是`scrollHeight`仍然会返回该元素的原始高度。
diff --git a/docs/dom/mutationobserver.md b/docs/dom/mutationobserver.md
index ace5853..0715565 100644
--- a/docs/dom/mutationobserver.md
+++ b/docs/dom/mutationobserver.md
@@ -44,7 +44,7 @@ var observer = new MutationObserver(function (mutations, observer) {
```javascript
var article = document.querySelector('article');
-var options = {
+var options = {
'childList': true,
'attributes':true
} ;
diff --git a/docs/oop/strict.md b/docs/oop/strict.md
index 3dffbe6..cc339c8 100644
--- a/docs/oop/strict.md
+++ b/docs/oop/strict.md
@@ -12,7 +12,7 @@
- 明确禁止一些不合理、不严谨的语法,减少 JavaScript 语言的一些怪异行为。
- 增加更多报错的场合,消除代码运行的一些不安全之处,保证代码运行的安全。
-- 提高编译器效率,增加运行速度。
+- 提高编译器效率,提升运行速度。
- 为未来新版本的 JavaScript 语法做好铺垫。
总之,严格模式体现了 JavaScript 更合理、更安全、更严谨的发展方向。
@@ -108,7 +108,7 @@ function notStrict() {
```javascript
// 对只读属性赋值会报错
'use strict';
-Object.defineProperty({}, 'a', {
+var obj = Object.defineProperty({}, 'a', {
value: 37,
writable: false
});
diff --git a/docs/oop/this.md b/docs/oop/this.md
index 6668047..6792c30 100644
--- a/docs/oop/this.md
+++ b/docs/oop/this.md
@@ -679,19 +679,19 @@ Array.prototype.slice.apply({length: 1}) // [undefined]
前面的按钮点击事件的例子,可以改写如下。
```javascript
-var o = new Object();
+var obj = new Object();
-o.f = function () {
- console.log(this === o);
+var func = function () {
+ console.log(this === obj);
}
-var f = function (){
- o.f.apply(o);
- // 或者 o.f.call(o);
+var handler = function (){
+ func.apply(obj);
+ // 或者 func.call(obj);
};
// jQuery 的写法
-$('#button').on('click', f);
+$('#button').on('click', handler);
```
上面代码中,点击按钮以后,控制台将会显示`true`。由于`apply()`方法(或者`call()`方法)不仅绑定函数执行时所在的对象,还会立即执行函数,因此不得不把绑定语句写在一个函数体内。更简洁的写法是采用下面介绍的`bind()`方法。
diff --git a/docs/operators/comparison.md b/docs/operators/comparison.md
index 3f34eca..002254a 100644
--- a/docs/operators/comparison.md
+++ b/docs/operators/comparison.md
@@ -99,7 +99,7 @@ x> '11' // true
x.valueOf = function () { return '1' };
x> '11' // false
-// 等同于 [2].valueOf()> '11'
+// 等同于 (function () { return '1' })()> '11'
// 即 '1'> '11'
```
@@ -114,8 +114,8 @@ x> '11' // false
// 等同于 [2].valueOf().toString()> [11].valueOf().toString()
// 即 '2'> '11'
-{ x: 2 }>= { x: 1 } // true
-// 等同于 { x: 2 }.valueOf().toString()>= { x: 1 }.valueOf().toString()
+({ x: 2 })>= ({ x: 1 }) // true
+// 等同于 ({ x: 2 }).valueOf().toString()>= ({ x: 1 }).valueOf().toString()
// 即 '[object Object]'>= '[object Object]'
```
diff --git a/docs/stdlib/date.md b/docs/stdlib/date.md
index 2b0326e..d0475da 100644
--- a/docs/stdlib/date.md
+++ b/docs/stdlib/date.md
@@ -317,15 +317,15 @@ d.toTimeString() // "00:00:00 GMT+0800 (CST)"
var d = new Date(2013, 0, 1);
d.toLocaleString()
-// 中文版浏览器为"2013年1月1日 上午12:00:00"
+// 中文版浏览器为"2013/1/1 00:00:00"
// 英文版浏览器为"1/1/2013 12:00:00 AM"
d.toLocaleDateString()
-// 中文版浏览器为"2013年1月1日"
+// 中文版浏览器为"2013/1/1"
// 英文版浏览器为"1/1/2013"
d.toLocaleTimeString()
-// 中文版浏览器为"上午12:00:00"
+// 中文版浏览器为"00:00:00"
// 英文版浏览器为"12:00:00 AM"
```
@@ -343,13 +343,13 @@ dateObj.toLocaleTimeString([locales[, options]])
var d = new Date(2013, 0, 1);
d.toLocaleString('en-US') // "1/1/2013, 12:00:00 AM"
-d.toLocaleString('zh-CN') // "2013/1/1 上午12:00:00"
+d.toLocaleString('zh-CN') // "2013/1/1 00:00:00"
d.toLocaleDateString('en-US') // "1/1/2013"
d.toLocaleDateString('zh-CN') // "2013/1/1"
d.toLocaleTimeString('en-US') // "12:00:00 AM"
-d.toLocaleTimeString('zh-CN') // "上午12:00:00"
+d.toLocaleTimeString('zh-CN') // "00:00:00"
```
`options`配置对象有以下属性。
@@ -479,7 +479,7 @@ d.getUTCDate() // 5
- `setDate(date)`:设置实例对象对应的每个月的几号(1-31),返回改变后毫秒时间戳。
- `setFullYear(year [, month, date])`:设置四位年份。
- `setHours(hour [, min, sec, ms])`:设置小时(0-23)。
-- `setMilliseconds()`:设置毫秒(0-999)。
+- `setMilliseconds(ms)`:设置毫秒(0-999)。
- `setMinutes(min [, sec, ms])`:设置分钟(0-59)。
- `setMonth(month [, date])`:设置月份(0-11)。
- `setSeconds(sec [, ms])`:设置秒(0-59)。
diff --git a/docs/stdlib/json.md b/docs/stdlib/json.md
index dfe1b76..c395d46 100644
--- a/docs/stdlib/json.md
+++ b/docs/stdlib/json.md
@@ -395,6 +395,15 @@ JSON.parse('{"a": 1, "b": 2}', f)
上面代码中,`JSON.parse()`的第二个参数是一个函数,如果键名是`a`,该函数会将键值加上10。
+`JSON.parse()`和`JSON.stringify()`可以结合使用,像下面这样写,实现对象的深拷贝。
+
+```javascript
+JSON.parse(JSON.stringify(obj))
+```
+
+上面这种写法,可以深度克隆一个对象,但是对象内部不能有 JSON
+不允许的数据类型,比如函数、正则对象、日期对象等。
+
## 参考链接
- MDN, [Using native JSON](https://developer.mozilla.org/en-US/docs/Using_native_JSON)
diff --git a/docs/stdlib/object.md b/docs/stdlib/object.md
index 51ba1e6..783175c 100644
--- a/docs/stdlib/object.md
+++ b/docs/stdlib/object.md
@@ -56,7 +56,7 @@ obj instanceof Object // true
`instanceof`运算符用来验证,一个对象是否为指定的构造函数的实例。`obj instanceof Object`返回`true`,就表示`obj`对象是`Object`的实例。
-如果参数是原始类型的值,`Object`方法将其转为对应的包装对象的实例(参见《原始类型的包装对象》一章)。
+如果参数是原始类型的值,`Object`方法将其转为对应的包装对象的实例(参见《包装对象》一章)。
```javascript
var obj = Object(1);
@@ -156,7 +156,7 @@ var obj = {
Object.getOwnPropertyNames(obj) // ["p1", "p2"]
```
-对于一般的对象来说,`Object.keys()`和`Object.getOwnPropertyNames()`返回的结果是一样的。只有涉及不可枚举属性时,才会有不一样的结果。`Object.keys`方法只返回可枚举的属性(详见《对象属性的描述对象》一章),`Object.getOwnPropertyNames`方法还返回不可枚举的属性名。
+对于一般的对象来说,`Object.keys()`和`Object.getOwnPropertyNames()`返回的结果是一样的。只有涉及不可枚举属性时,才会有不一样的结果。`Object.keys`方法只返回可枚举的属性(详见《属性描述对象》一章),`Object.getOwnPropertyNames`方法还返回不可枚举的属性名。
```javascript
var a = ['Hello', 'World'];
@@ -231,7 +231,7 @@ obj.valueOf() === obj // true
上面代码比较`obj.valueOf()`与`obj`本身,两者是一样的。
-`valueOf`方法的主要用途是,JavaScript 自动类型转换时会默认调用这个方法(详见《数据类型转换》一章)。
+`valueOf`方法的主要用途是,JavaScript 自动类型转换时会默认调用这个方法(详见《数据类型的转换》一章)。
```javascript
var obj = new Object();
@@ -308,7 +308,7 @@ var obj = {};
obj.toString() // "[object Object]"
```
-上面代码调用空对象的`toString`方法,结果返回一个字符串`object Object`,其中第二个`Object`表示该值的构造函数。这是一个十分有用的判断数据类型的方法。
+上面代码调用空对象的`toString`方法,结果返回一个字符串`[object Object]`,其中第二个`Object`表示该值的构造函数。这是一个十分有用的判断数据类型的方法。
由于实例对象可能会自定义`toString`方法,覆盖掉`Object.prototype.toString`方法,所以为了得到类型字符串,最好直接使用`Object.prototype.toString`方法。通过函数的`call`方法,可以在任意值上调用这个方法,帮助我们判断这个值的类型。
diff --git a/docs/stdlib/regexp.md b/docs/stdlib/regexp.md
index 8e306e0..5a1d884 100644
--- a/docs/stdlib/regexp.md
+++ b/docs/stdlib/regexp.md
@@ -104,7 +104,7 @@ r.lastIndex = 4;
r.test(s) // false
r.lastIndex // 0
-r.test(s)
+r.test(s) // true
```
上面代码指定从字符串的第五个位置开始搜索,这个位置为空,所以返回`false`。同时,`lastIndex`属性重置为`0`,所以第二次执行`r.test(s)`会返回`true`。
@@ -150,7 +150,7 @@ r2.exec(s) // null
上面代码中,正则对象`r1`匹配成功,返回一个数组,成员是匹配结果;正则对象`r2`匹配失败,返回`null`。
-如果正则表示式包含圆括号(即含有"组匹配"),则返回的数组会包括多个成员。第一个成员是整个匹配成功的结果,后面的成员就是圆括号对应的匹配成功的组。也就是说,第二个成员对应第一个括号,第三个成员对应第二个括号,以此类推。整个数组的`length`属性等于组匹配的数量再加1。
+如果正则表达式包含圆括号(即含有"组匹配"),则返回的数组会包括多个成员。第一个成员是整个匹配成功的结果,后面的成员就是圆括号对应的匹配成功的组。也就是说,第二个成员对应第一个括号,第三个成员对应第二个括号,以此类推。整个数组的`length`属性等于组匹配的数量再加1。
```javascript
var s = '_x_x';
diff --git a/docs/types/general.md b/docs/types/general.md
index 8454b44..6d512ef 100644
--- a/docs/types/general.md
+++ b/docs/types/general.md
@@ -2,7 +2,7 @@
## 简介
-JavaScript 语言的每一个值,都属于某一种数据类型。JavaScript 的数据类型,共有六种。(ES6 又新增了第七种 Symbol 类型的值,本教程不涉及。)
+JavaScript 语言的每一个值,都属于某一种数据类型。JavaScript 的数据类型,共有六种。(ES6 又新增了 Symbol 和 BigInt 数据类型,本教程不涉及。)
- 数值(number):整数和小数(比如`1`和`3.14`)。
- 字符串(string):文本(比如`Hello World`)。
diff --git a/docs/types/null-undefined-boolean.md b/docs/types/null-undefined-boolean.md
index 9a76679..129dda3 100644
--- a/docs/types/null-undefined-boolean.md
+++ b/docs/types/null-undefined-boolean.md
@@ -35,7 +35,7 @@ undefined == null
既然含义与用法都差不多,为什么要同时设置两个这样的值,这不是无端增加复杂度,令初学者困扰吗?这与历史原因有关。
-1995年 JavaScript 诞生时,最初像 Java 一样,只设置了`null`表示"无"。根据 C 语言的传统,`null`可以自动转为`0`。
+1995年 JavaScript 诞生时,最初像 Java 一样,只设置了`null`表示"无"。根据 C 语言的传统,`null`可以自动转为`0`。
```javascript
Number(null) // 0
@@ -46,7 +46,7 @@ Number(null) // 0
但是,JavaScript 的设计者 Brendan Eich,觉得这样做还不够。首先,第一版的 JavaScript 里面,`null`就像在 Java 里一样,被当成一个对象,Brendan Eich 觉得表示"无"的值最好不是对象。其次,那时的 JavaScript 不包括错误处理机制,Brendan Eich 觉得,如果`null`自动转为0,很不容易发现错误。
-因此,他又设计了一个`undefined`。区别是这样的:`null`是一个表示"空"的对象,转为数值时为`0`;`undefined`是一个表示"此处无定义"的原始值,转为数值时为`NaN`。
+因此,他又设计了一个`undefined`。区别是这样的:`null`是一个表示"空"的对象,转为数值时为`0`;`undefined`是一个表示"此处无定义"的原始值,转为数值时为`NaN`。
```javascript
Number(undefined) // NaN
diff --git a/docs/types/number.md b/docs/types/number.md
index 64f0592..53ebfb5 100644
--- a/docs/types/number.md
+++ b/docs/types/number.md
@@ -43,7 +43,7 @@ JavaScript 内部,所有数字都是以64位浮点数形式储存,即使整
上面公式是正常情况下(指数部分在0到2047之间),一个数在 JavaScript 内部实际的表示形式。
-精度最多只能到53个二进制位,这意味着,绝对值小于2的53次方的整数,即-2
53到2
53,都可以精确表示。
+精度最多只能到53个二进制位,这意味着,绝对值小于2的53次方的整数,即-2
53 + 1 到 2
53 - 1,都可以精确表示。
```javascript
Math.pow(2, 53)
@@ -280,6 +280,12 @@ NaN * 32 // NaN
NaN / 32 // NaN
```
+但是,ES6 引入指数运算符(`**`)后,出现了一个例外。
+
+```javascript
+NaN ** 0 // 1
+```
+
### Infinity
**(1)含义**
@@ -552,7 +558,15 @@ parseFloat('3.14more non-digit characters') // 3.14
parseFloat('\t\v\r12.34\n ') // 12.34
```
-如果参数不是字符串,或者字符串的第一个字符不能转化为浮点数,则返回`NaN`。
+如果参数不是字符串,则会先转为字符串再转换。
+
+```javascript
+parseFloat([1.23]) // 1.23
+// 等同于
+parseFloat(String([1.23])) // 1.23
+```
+
+如果字符串的第一个字符不能转化为浮点数,则返回`NaN`。
```javascript
parseFloat([]) // NaN
diff --git a/package.json b/package.json
index b67124a..479b7bb 100644
--- a/package.json
+++ b/package.json
@@ -14,11 +14,6 @@
"server": "loppo server",
"test": "echo \"Error: no test specified\" && exit 1"
},
- "husky": {
- "hooks": {
- "pre-push": "npm update"
- }
- },
"repository": {
"type": "git",
"url": "git+https://github.com/wangdoc/javascript-tutorial.git"
@@ -35,9 +30,8 @@
},
"homepage": "https://github.com/wangdoc/javascript-tutorial",
"dependencies": {
- "gh-pages": "^3.2.3",
- "husky": "^4.3.8",
+ "gh-pages": "6.x",
"loppo": "^0.6.24",
- "loppo-theme-wangdoc": "^0.6.1"
+ "loppo-theme-wangdoc": "^0.7.3"
}
}