Skip to content

Commit

Permalink
docs: edit grammar/number/parseInt
Browse files Browse the repository at this point in the history
  • Loading branch information
ruanyf committed Feb 11, 2016
1 parent 3292bab commit 0870999
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 87 deletions.
125 changes: 58 additions & 67 deletions grammar/number.md
Original file line number Diff line number Diff line change
Expand Up @@ -406,24 +406,32 @@ isFinite(NaN) // false

**(1)基本用法**

`parseInt`方法可以将字符串或小数转化为整数。如果字符串头部有空格,空格会被自动去除。
`parseInt`方法用于将字符串转为整数。如果字符串头部有空格,空格会被自动去除。

```javascript
parseInt('123') // 123
parseInt(1.23) // 1
parseInt(' 81') // 81
```

如果`parseInt`的参数不是字符串,则会先转为字符串再转换。

```javascript
parseInt(1.23) // 1
// 等同于
parseInt('1.23') // 1
```

字符串转为整数的时候,是一个个字符依次转换,如果遇到不能转为数字的字符,就不再进行下去,返回已经转好的部分。

```javascript
parseInt('8a') // 8
parseInt('12**') // 12
parseInt('12.34') // 12
parseInt('0xf00') // 3840
parseInt('15e2') // 15
parseInt('15px') // 15
```

上面代码中,`parseInt`的参数都是字符串,结果只返回字符串头部可以转为数字的部分。最后一行的`0xf00`之所以可以转为数字,因为如果开头两个字符是`0x``0X``parseInt`将其视为十六进制数(下文有进一步解释)。
上面代码中,`parseInt`的参数都是字符串,结果只返回字符串头部可以转为数字的部分。

如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回`NaN`

Expand All @@ -432,108 +440,91 @@ parseInt('abc') // NaN
parseInt('.3') // NaN
parseInt('') // NaN
parseInt('+') // NaN
parseInt('+1') // 1
```

**(2)进制转换**
`parseInt`的返回值只有两种可能,不是一个十进制整数,就是`NaN`

`parseInt`方法还可以接受第二个参数(2到36之间),表示被解析的值的进制,返回该值对应的十进制数
如果字符串以`0x``0X`开头,`parseInt`会将其按照十六进制数解析

```javascript
parseInt(1000, 2) // 8
parseInt(1000, 6) // 216
parseInt(1000, 8) // 512
parseInt('0x10') // 16
```

上面代码中,二进制、六进制、八进制的1000,分别等于十进制的8、216和512。这意味着,可以用`parseInt`方法进行进制的转换。

如果第二个参数不是数值,会被自动转为一个整数。这个整数只有在2到36之间,才能得到有意义的结果,超出这个范围,则返回`NaN`。如果第二个参数是`0``undefined``null`,则直接忽略。
如果字符串以`0`开头,ES5规定`parseInt`按照10进制解析。

```javascript
parseInt(10, 37) // NaN
parseInt(10, 1) // NaN
parseInt(10, 0) // 10
parseInt(10, null) // 10
parseInt(10, undefined) // 10
parseInt('011') // 11
```

需要注意的是,进制转换的时候,参数是字符串或数值,`parseInt`的行为不一致。如果第一个参数是数值,会将这个数值先转为十进制,然后再应用第二个参数
对于那些会自动转为科学计数法的数字,`parseInt`会将科学计数法的表示方法视为字符串,因此导致一些奇怪的结果

```javascript
parseInt(0x11, 36) // 43
parseInt(17, 36) // 43
```

上面代码中,`0x11`会被先转为十进制的17,然后再用36进制解读这个17,最后返回结果43。

如果第一个参数是字符串,则会直接用指定进制解读这个字符串。
parseInt(1000000000000000000000.5) // 1
// 等同于
parseInt('1e+21') // 1

```javascript
parseInt('0x11', 36) // 42805
parseInt('x', 36) // 33
parseInt(0.0000008) // 8
// 等同于
parseInt('8e-7') // 8
```

上面代码中,字符串`0x11`会被直接当作一个36进制的数。由于字符`x`在36进制中代表33,导致`0x11`被解读为42805。
**(2)进制转换**

下面是更多的例子
`parseInt`方法还可以接受第二个参数(2到36之间),表示被解析的值的进制,返回该值对应的十进制数。`parseInt`的第二个参数默认为10,即默认情况下是十进制转十进制

```javascript
parseInt(010, 10) // 8
parseInt('010', 10) // 10
parseInt('1000') // 1000
parseInt('1000', 10) // 1000

parseInt(010, 2) // NaN
parseInt('010', 2) // 2
parseInt('1000', 2) // 8
parseInt('1000', 6) // 216
parseInt('1000', 8) // 512
```

parseInt(010, 8) // NaN
parseInt('010', 8) // 8
上面代码中,二进制、六进制、八进制的1000,分别等于十进制的8、216和512。这意味着,可以用`parseInt`方法进行进制的转换。

parseInt(020, 10) // 16
parseInt('020', 10) // 20
如果第二个参数不是数值,会被自动转为一个整数。这个整数只有在2到36之间,才能得到有意义的结果,超出这个范围,则返回`NaN`。如果第二个参数是`0``undefined``null`,则直接忽略。

parseInt(020, 8) // 14
parseInt('020', 8) // 16
```javascript
parseInt('10', 37) // NaN
parseInt('10', 1) // NaN
parseInt('10', 0) // 10
parseInt('10', null) // 10
parseInt('10', undefined) // 10
```

上面代码中,`010`会被先转为十进制8,然后再应用第二个参数,由于二进制和八进制中没有8这个数字,所以`parseInt(010, 2)``parseInt(010, 8)`返回`NaN`。同理,数值`020`会被先转为十进制的16,然后再应用第二个参数。

如果第一个参数是以`0x``0X`开头的字符串,而第二个参数省略或为0,则`parseInt`自动将第二个参数设为16。
如果字符串包含对于指定进制无意义的字符,则返回`NaN`

```javascript
parseInt('0xFF') // 255
parseInt('0xFF', 0) // 255
parseInt('0xFF', 16) // 255
parseInt('0xFF', 10) // 0
parseInt('0xFF', 17) // 0
parseInt('1546', 2) // 1
parseInt('546', 2) // NaN
```

上面代码中,第二个参数除了0、16和省略,其他情况都会依次解析第一个参数,直到遇到第一个不可解析字符
上面代码中,对于二进制来说,`1`是有意义的字符,`5``4``6`都是无意义的字符,所以第一行返回1,第二行返回`NaN`

**(3)八进制的前缀0**

`parseInt`的很多复杂行为,都是由八进制的前缀0引发的。
前面说过,如果`parseInt`的第一个参数不是字符串,会被先转为字符串。这会导致一些令人意外的结果。

```javascript
parseInt(010, 8) // NaN
parseInt('010', 8) // 8
parseInt(0x11, 36) // 43
// 等同于
parseInt(String(0x11), 36)
parseInt('17', 36)
```

上面代码中,数值形式和字符串形式的`010`会得到不一样的处理结果。这增加编程处理的复杂性。

因此,ECMAScript 5不再允许parseInt将带有前缀0的数字,视为八进制数,而是要求忽略这个`0`。但是,为了保证兼容性,大部分浏览器并没有部署这一条规定。
上面代码中,十六进制的`0x11`会被先转为十进制的17,再转为字符串。然后,再用36进制解读字符串`17`,最后返回结果43。

**(4)科学计数法**

对于那些会自动转为科学计数法的数字,`parseInt`会将科学计数法的表示方法视为字符串,因此导致一些奇怪的结果。
这种处理方式,对于八进制的前缀0,尤其需要注意。

```javascript
parseInt(1000000000000000000000.5, 10) // 1
// 等同于
parseInt('1e+21', 10) // 1

parseInt(0.0000008, 10) // 8
// 等同于
parseInt('8e-7', 10) // 8
parseInt(011, 2) // NaN
parseInt('011', 2) // 3
```

上面代码中,第一行的`011`会被先转为字符串`9`,因为`9`不是二进制的有效字符,所以返回`NaN`。第二行的字符串`011`,会被当作二进制处理,返回3。

ES5不再允许将带有前缀0的数字,视为八进制数,而是要求忽略这个`0`。但是,为了保证兼容性,大部分浏览器并没有部署这一条规定。

### parseFloat()

`parseFloat`方法用于将一个字符串转为浮点数。
Expand Down
43 changes: 34 additions & 9 deletions nodejs/npm.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,31 +237,29 @@ console.log(backbone.VERSION)
## 模块标签
Npm允许为模块的某个版本,新建一个标签。
npm允许为模块的某个版本,新建一个标签。
```bash
$ npm dist-tag add <pkg>@<version> [<tag>]
```
同一种方法是发布的时候,加上标签。
另一种方法是发布的时候,加上标签。
```bash
$ npm publish --tag=beta
```
有了标签以后,就可以指定安装该标签的版本,或者该标签的依赖
有了标签以后,就可以指定安装该标签的版本。
```bash
# 安装模块
$ npm install <name>@<tag>

# 安装依赖
# 或者
$ npm install --tag <tag>
```
常见的标签有`latest``stable``next`等。
Npm默认会为最新一次发布的版本,新建`latest`标签。然后,下载的时候,默认是下载带有`latest`标签的版本。但是,这可能并不是我们想要的行为。比如,当前最新版本是4.2版,然后发布了一个3.6版,`latest`的标签就会打在3.6版上面,用户`npm install`安装的就是这个版本。
npm默认会为最新一次发布的版本,新建`latest`标签。然后,下载的时候,默认是下载带有`latest`标签的版本。但是,这可能并不是我们想要的行为。比如,当前最新版本是4.2版,然后发布了一个3.6版,`latest`的标签就会打在3.6版上面,用户`npm install`安装的就是这个版本。
为了避免这个问题,可以为3.6版加上`previous`标签。
Expand Down Expand Up @@ -908,7 +906,7 @@ Password: YOUR_PASSWORD
Email: YOUR_EMAIL@domain.com
```

## npm publish
## npublish

`npm publish`用于将当前模块发布到`npmjs.com`。执行之前,需要向`npmjs.com`申请用户名。

Expand All @@ -922,7 +920,7 @@ $ npm adduser
$ npm login
```

最后,使用npm publish命令发布
登录以后,就可以使用`npm publish`命令发布

```bash
$ npm publish
Expand All @@ -940,6 +938,32 @@ $ npm publish --tag beta
$ npm init --scope=<yourscope>
```

如果你的模块是用ES6写的,那么发布的时候,最好转成ES5。首先,需要安装Babel。

```javascript
$ npm install --save-dev babel-cli@6 babel-preset-es2015@6
```

然后,在`package.json`里面写入`build`脚本。

```javascript
"scripts": {
"build": "babel source --presets babel-preset-es2015 --out-dir distribution",
"prepublish": "npm run build"
}
```

运行上面的脚本,会将`source`目录里面的ES6源码文件,转为`distribution`目录里面的ES5源码文件。然后,在项目根目录下面创建两个文件`.npmignore``.gitignore`,分别写入以下内容。

```javascrip
// .npmignore
source
// .gitignore
node_modules
distribution
```

## npm version

`npm version`命令用来修改项目的版本号。当你完成代码修改,要发布新版本的时候,就用这个命令更新一下软件的版本。
Expand Down Expand Up @@ -989,3 +1013,4 @@ $ npm deprecate my-thing@"< 0.2.3" "critical bug fixed in v0.2.3"
- justjs, [npm link: developing your own npm modules without tears](http://justjs.com/posts/npm-link-developing-your-own-npm-modules-without-tears)
- hoodie-css, [Development Environment Help](https://github.com/hoodiehq/hoodie-css/blob/feature/build-automation/DEVELOPMENT.md)
- Stephan Bönnemann, [How to make use of npm’s package distribution tags to create release channels](https://medium.com/greenkeeper-blog/one-simple-trick-for-javascript-package-maintainers-to-avoid-breaking-their-user-s-software-and-to-6edf06dc5617#.5omqgsg45)
- Alex Booker, [How to Build and Publish ES6 npm Modules Today, with Babel](https://booker.codes/how-to-build-and-publish-es6-npm-modules-today-with-babel/)
18 changes: 7 additions & 11 deletions stdlib/object.md
Original file line number Diff line number Diff line change
Expand Up @@ -556,33 +556,30 @@ var owner = {
Object.defineProperty(car, 'ownerInfo', {value: owner, enumerable: false});
car.ownerInfo // {id: 12, name: "Jack"}

JSON.stringify(car) // '{id: 123, color: "red", owner: 12}'
JSON.stringify(car) // "{"id": 123,"color": "red","ownerId": 12}"
```
上面代码中,`owner`对象作为注释,加入`car`对象。由于`ownerInfo`属性的`enumerable``false`,所以`JSON.stringify`最后正式输出`car`对象时,会忽略`ownerInfo`属性。
上面代码中,`owner`对象作为注释,加入`car`对象。由于`ownerInfo`属性不可枚举,所以`JSON.stringify`方法最后输出`car`对象时,会忽略`ownerInfo`属性。
这提示我们,如果你不愿意某些属性出现在JSON输出之中,可以把它的`enumerable`属性设为`false`
### Object.getOwnPropertyNames()
Object.getOwnPropertyNames方法返回直接定义在某个对象上面的全部属性的名称,而不管该属性是否可枚举。
{% highlight javascript %}
```javascript
var o = Object.defineProperties({}, {
p1: { value: 1, enumerable: true },
p2: { value: 2, enumerable: false }
});

Object.getOwnPropertyNames(o)
// ["p1", "p2"]
{% endhighlight %}
```
一般来说,系统原生的属性(即非用户自定义的属性)都是不可枚举的。
{% highlight javascript %}
```javascript
// 比如,数组实例自带length属性是不可枚举的
Object.keys([]) // []
Object.getOwnPropertyNames([]) // [ 'length' ]
Expand All @@ -597,10 +594,9 @@ Object.getOwnPropertyNames(Object.prototype)
// 'isPrototypeOf',
// 'propertyIsEnumerable',
// 'toString']
```
{% endhighlight %}
上面代码可以看到,数组的实例对象([])没有可枚举属性,不可枚举属性有length;Object.prototype对象也没有可枚举属性,但是有不少不可枚举属性。
上面代码可以看到,数组的实例对象(`[]`)没有可枚举属性,不可枚举属性有length;Object.prototype对象也没有可枚举属性,但是有不少不可枚举属性。
### Object.prototype.propertyIsEnumerable()
Expand Down

0 comments on commit 0870999

Please sign in to comment.