0x01.犀牛ch1-3

作者: Anduril | 来源:发表于2018-04-22 08:24 被阅读7次

官网 http://shop.oreilly.com/product/9780596805531.do

ch1 语言介绍

内容 HTML 行为JS 样式CSS
高端、动态、弱语言,非常适合面向对象和函数式编程风格
特点:一等函数(first-class function)、基于原型(prototype-based)

输入输出功能由宿主环境(host enviroment)提供 ,基于浏览器的API统称为客户端JavaScript

函数和对象合写在一起,函数就变成了"方法 method"

ch2 词法结构

标签和属性必须小写.
Js会忽略程序中标识(token)之间的空格,也会忽略换行符。
回车符(\u000D) 加 换行符(\u000A)在一起被解析为一个单行结束符。
Unicode 转义序列 \uXXXX X为16进制数 "café" === 'caf\u00e9'

直接量( literal)是程序中直接使用的数据值。 (数字、字符串、正则表达式、数组、对象等直接量)
标识符必须以字母、下划线(_)或美元符($)开始。后续的字符可以是字母、数字、下划线或美元符。

只有在缺少了分号就无法正确解析代码的时候,JavaScript才会填补分号。如果当前语句和随后的非空格字符不能当成一个整体来解析的话,JavaScript就在当前语句行结束处填补分号

var a
a
=
3 
console.log(a)
//解析成 var a; a = 3; console.log(a);

var x = 0 // 这里省略了分号
;[x,x+1,x+2].forEach(console.log) // 前面的分号保证了正确地语句解析

ch3 类型、值、变量

数据类型分类:

  • 原始类型(primitive type)
  • 对象类型(object type)

原始类型包括

  • 数字
  • 字符串
  • 布尔值
  • null(空)
  • undefined(未定义)

对象类型(object type) 是属性(property)的集合。

  • 全局对象(global object)
  • 数组(array)带编号的有序集合
  • 函数

**函数 **
如果函数初始化(使用new运算符)一个新建对象,我们称之为构造函数(constructor)。每个构造函数定义了一类(class)对象--构造函数初始化对象组成的集合。类可以看做对象类型的子类型。

除了数组(array)类和函数(function)类之外,javascript还定义了其它三种有用的类。

  • 日期(date)定义了代表日期的对象。
  • 正则(regExp)定义了正则表达式的对象。
  • 错误(error)类定义了那行表示javascript程序中运行时错误和语法错误对象。

js中只有对象才能拥有方法。数字,字符串,布尔值也拥有自己的方法。只有null和undefined是无法拥有方法的值。

  • 可变(mutable)
  • 不可变(immutable)
    对象和数组属于可变类型
    字符串、数字、布尔值、null和undefined属于不可改变的类型。

js的变量是无类型的(untyped),变量可以被赋予任何类型的值,使用var关键字来声明(declare)变量。javascript采用语法作用域,不在任何函数内声明的变量称为全局变量(global variable)它在程序中任何地方都是可见的。

3.1数字

数字均用浮点数值表示。采用64位浮点格式表示数字,实际的操作(数组索引,位操作符)则是基于32位整数。
数字直接量(numeric literal)
十六进制 “0x”或“0X” 八进制 0开头 0377 ECMAScript 6的严格模式下,八进制直接量是明令禁止的

溢出(overflow)
的数字上限(溢出),结果为一个特殊的无穷大(infinity)值,以Infinity表示。当负数的值超过了负数范围,结果为负无穷大以-Infinity表示。
无穷大值:基于它们的加、减、乘和除运算结果还是无穷大值(保留正负号)。
下溢(underflow)
当运算结果无限接近于零并比JavaScript能表示的最小值还小的时候发生的一种情形。返回0。负数发生下溢时,返回“负零”。

被零整除
被零整除并不报错:返回无穷大(Infinity)或负无穷大(-Infinity)。
零除以零运算结果也是一个非数字(not-a-number)值,用NaN表示。无穷大除以无穷大、给任意负数作开方运算或者算术运算符与不是数字或无法转换为数字的操作数一起使用时都将返回NaN。
NaN和任何值都不相等,包括自身。当且仅当x为NaN的时候,表达式x!=x的结果才为true。
函数isNaN(),如果参数是NaN或者是一个非数字值(比如字符串和对象),则返回true。
函数isFinite(),在参数不是NaN、Infinity或-Infinity的时候返回true。

Infinity/0   //Infinity
0/0    //NaN
Infinity/Infinity    //NaN
Number.MIN_VALUE/2     //下溢 0 

Infinity==-Infinity  //=>false  非数值和任何值(包括自身)都不相等。 

浮点数表示法精度
二进制浮点数表示法并不能精确表示十进制的分数。

.3-.2  //=>0.09999999999999998
.2-.1  //=>0.1

3.2 文本

字符串(string)是一组由16位值组成的不可变的有序序列。JavaScript通过字符串类型来表示文本。字符串的长度(length)是其所含16位值的个数。空字符串(empty string)长度为0,JavaScript中并没有表示单个字符的“字符型”。

//ECMAScript 5中,字符串直接量可以拆分成数行,每行必须以反斜线(\)结束,反斜线和行结束符都不算是字符串直接量的内容。
//=> "onelongline"
"one\
long\
line"

转义字符(escape sequence)

转义字符 含义
\o NUL字符(\u0000)  
\b 退格符(\u0008)
\t 水平制表符(\u0009)   
\n 换行符(\u000A)  
\v 垂直制表符(\u000B)
\f 换页符(\u000C) 
\r 回车符(\u000D) 
\" 双引号(\u0022)
\' 撇号或单引号(\u0027)  
\\ 反斜线(\u005C) 
\xXX 由两位十六进制数XX指定的Latin-1字符 
\uXXXX 由4位十六进制数XXXX指定的Unicode字符

在JavaScript中字符串是固定不变的,一些方法都返回新字符串,原字符串本身并没有发生改变。

布尔值

任意JavaScript的值都可以转换为布尔值。JavaScript期望使用一个布尔值的时候,假值会被当成false,真值会被当成true。
false和下面6个可以转换成false的值有时称做“假值”(falsy value);所有其他值,包括所有对象(数组)都会转换成true,其他值称做“真值”(truthy value)。

undefined
null
0
-0
NaN
"" // 空字符串

console.log( false == null )      // false
console.log( false == undefined ) // false
console.log( false == 0 )         // true
console.log( false == '' )        // true
console.log( false == NaN )       // false

参照标准ToBoolean http://www.ecma-international.org/ecma-262/5.1/

null、undefined

null是关键字,描述“空值”。

//null认为是一个特殊的对象值,含义是“非对象”。
//null是它自有类型的唯一一个成员,它可以表示数字、字符串和对象是“无值”的。
typeof(null)  //=> object

undefined(未定义的值)表示更深层次的“空值”。

  • 变量没有初始化
  • 查询对象属性或数组元不存在
  • 函数没有返回任何值,则返回undefined
  • 引用没有提供实参的函数形参的值
//undefined是预定义的全局变量,它的值就是“未定义”。
//undifined是这个类型的唯一成员
typeof(undifined) //=> undifined
null == undefined  //=> true

如果你想将它们赋值给变量或者属性,或将它们作为参数传入函数,最佳选择是使用null。

全局对象(global object)

当JavaScript解释器启动时(或者任何Web浏览器加载新页面的时候),它将创建一个新的全局对象,并定义如下属性:全局属性、全局函数、构造函数、全局对象

//使用JavaScript关键字this来引用全局对象
var global = this; // 定义一个引用全局对象的全局变量

JavaScript对象(object)是一种复合值:它是属性(property)或已命名值的集合,每个属性都由“名/值对”(值可以是原始值,比如数字、字符串,也可以是对象)构成。通过“.”符号来引用属性值。当属性值是一个函数的时候,称其为方法。通过o.m()来调用对象o中的方法。

JavaScript是一种面向对象的语言。数据类型本身可以定义方法(method)来使用值。

a.sort(); // sort(a)的面向对象的版本

从技术上讲,只有JavaScript对象才能拥有方法。然而,数字、字符串和布尔值也可以拥有自己的方法。在JavaScript中,只有null和undefined是无法拥有方法的值。

包装对象

存取字符串、数字或布尔值的属性时创建的临时对象称做包装对象(一种实现细节),它只是偶尔用来区分字符串值和字符串对象、数字和数值对象以及布尔值和布尔对象。
字符串、数字和布尔值不是对象,为什么它会有属性呢?只要引用了属性,JavaScript就会将字面量通过调用new String()/Number()/ Boolean()构造函数创建一个临时对象,这些方法的调用均是来自于这个临时对象。null和undefined没有包装对象:访问它们的属性会造成一个类型错误。
一旦属性引用结束,这个新创建的对象就会销毁。JavaScript解释器有自己的内存管理机制,可以自动对内存进行垃圾回收(garbage collection)。

//“==”等于运算符将原始值和其包装对象视为相等,
var s = "test", n = 1, b = true;  // 一个字符串、数字和布尔值
var S = new String(s);   // 一个字符串对象
var N = new Number(n);   // 一个数值对象
var B = new Boolean(b);   // 一个布尔对象

如果函数用来初始化(使用new运算符)一个新建的对象,我们称之为构造函数(constructor)。

  • 数组(Array)类
  • 函数(Function)类
  • 日期(Date)类定义了代表日期的对象。
  • 正则(RegExp)类定义了表示正则表达式的对象,强大通用的文本处理工具。
  • 错误(Error)类定义了那些表示JavaScript程序中运行时错误和语法错误的对象。

不可变的原始值和可变的对象引用

可变(mutable)类型和不可变(immutable)类型。
JavaScript中的原始值(undefined、null、布尔值、数字和字符串)是不可更改的:任何方法都无法更改(或“突变”)一个原始值。原始值的比较是值的比较:只有在它们的值相等时它们才相等。
对象(包括数组和函数)的值是可修改的。对象称为引用类型(reference type), 对象值都是引用(reference),对象的比较均是引用的比较:当且仅当它们引用同一个基对象时,它们才相等。

类型转换

JavaScript一个值转换为另一个值并不意味着两个值相等。
null和undefined转换成对象的地方都会造成一个类型错误(TypeError)异常。
除了null或undefined之外的任何值都具有toString()方法,这个方法的执行结果通常和String()方法的返回结果一致。
显式类型转换最简单的方法就是使用Boolean()、Number()、String()或Object()函数。

运算符隐式转换

  • “+”运算符的一个操作数是字符串,将会把另外一个操作数转换为字符串。
  • 一元“+”运算符将其操作数转换为数字。
  • 一元“!”运算符将其操作数转换为布尔值并取反。

数字到字符串(number-to-string)

toString()方法

可以接收表示转换基数(radix)的可选参数,如果不指定此参数,转换规则将是基于十进制。支持进制数(范围在2~36之间)

toFixed()

根据小数点后的指定位数将数字转换为字符串,它从不使用指数记数法。

toExponential()

使用指数记数法将数字转换为指数形式的字符串,其中小数点前只有一位,小数点后的位数则由参数指定(也就是说有效数字位数比指定的位数要多一位)

toPrecision()

根据指定的有效数字位数将数字转换成字符串。如果有效数字的位数少于数字整数部分的位数,则转换成指数形式。

字符串到数字(string-to-number)

parseInt()函数 parseFloat()函数(全局函数)

如果字符串前缀是“0x”或者“0X”,parseInt()将其解释为十六进制数注2,parseInt()和parseFloat()都会跳过任意数量的前导空格,尽可能解析更多数值字符,并忽略后面的内容。如果第一个非空格字符是非法的数字直接量,将最终返回NaN。
parseInt()可以接收第二个可选参数,这个参数指定数字转换的基数,合法的取值范围是2~36

对象转换为原始值

所有的对象(包括数组和函数)都转换为true。new Boolean(false)是一个对象而不是原始值,它将转换为true。

++只适用于本地对象(native object)++

toString()

  • 默认的toString()方法返回 "[object Object]"
  • 数组类(Array class)将每个数组元素转换为一个字符串,并在元素之间添加逗号后合并成结果字符串。
  • 函数类(Function class)返回这个函数的实现定义的表示方式。
  • 日期类(Date class)返回了一个可读的(可被JavaScript解析的)日期和时间字符串。
  • RegExp类(RegExp class)将RegExp对象转换为表示正则表达式直接量的字符串。

valueOf()

如果存在任意原始值,它就默认将对象转换为表示它的原始值。
对象是复合值,而且大多数对象无法真正表示为一个原始值,因此默认的valueOf()方法简单地返回对象本身,而不是返回一个原始值。

  • 数组、函数和正则表达式 返回对象本身。
  • 日期类 返回它的一个内部表示:1970年1月1日以来的毫秒数。

对象到字符串(object-to-string)

  1. 如果对象具有toString()方法,则调用这个方法。如果它返回一个原始值,JavaScript将这个值转换为字符串(如果本身不是字符串的话),并返回这个字符串结果。
  2. 如果对象没有toString()方法,或者这个方法并不返回一个原始值,那么JavaScript会调用valueOf()方法。如果存在这个方法,则JavaScript调用它。如果返回值是原始值,JavaScript将这个值转换为字符串(如果本身不是字符串的话),并返回这个字符串结果。
  3. 否则,JavaScript无法从toString()或valueOf()获得一个原始值,因此这时它将抛出一个类型错误异常。

对象到数字(object-to-number)

  1. 如果对象具有valueOf()方法,后者返回一个原始值,则JavaScript将这个原始值转换为数字并返回这个数字。
  2. 否则,如果对象具有toString()方法,后者返回一个原始值,则JavaScript将其转换并返回。
  3. 否则,JavaScript抛出一个类型错误异常。

运算符导致的隐式转换中日期类型最特殊。

变量声明

JavaScript变量是无类型的(untyped),变量可以被赋予任何类型的值,同样一个变量也可以重新赋予不同类型的值。使用var关键字来声明(declare)变量。

变量作用域

JavaScript没有块级作用域(block scope)。 函数作用域(function scope):变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。

声明提前(hoisting)

JavaScript函数里声明的所有变量(但不涉及赋值)都被“提前”至函数体的顶部

var scope = "global";
function f() {
 console.log(scope);  // 输出"undefined",而不是"global"
 var scope = "local"; // 变量在这里赋初始值,但变量本身在函数体内任何地方均是有定义的
 console.log(scope);  // 输出"local"
}

全局变量(global variable)

当声明一个JavaScript全局变量时,实际上是定义了全局对象的一个属性。

  • 当使用var声明一个变量时,创建的这个属性是不可配置的,无法通过delete运算符删除。
  • 在非严格模式并给一个未声明的变量赋值的话,JavaScript会自动创建一个全局变量,是可配值的。

作用域链(scope chain)

JavaScript是基于词法作用域(lexical scoping)的语言:通过阅读包含变量定义在内的数行源码就能知道变量的作用域。

  • 全局变量在程序中始终都是有定义的。
  • 局部变量在声明它的函数体内以及其所嵌套的函数内始终是有定义的。

当JavaScript需要查找变量x的值的过程称做“变量解析”(variable resolution)

在最顶层代码中(也就是不包含在任何函数定义内的代码),作用域链由一个全局对象组成。

在不包含嵌套的函数体内,作用域链上有两个对象,
第一个是定义函数参数和局部变量的对象,
第二个是全局对象。
在一个嵌套的函数体内,作用域链上至少有三个对象。

当定义一个函数时,它实际上保存一个作用域链。当调用这个函数时,它创建一个新的对象来存储它的局部变量,并将这个对象添加至保存的那个作用域链上,同时创建一个新的更长的表示函数调用作用域的“链”。对于嵌套函数来讲,事情变得更加有趣,每次调用外部函数时,内部函数又会重新定义一遍。因为每次调用外部函数的时候,作用域链都是不同的。内部函数在每次定义的时候都有微妙的差别——在每次调用外部函数时,内部函数的代码都是相同的,而且关联这段代码的作用域链也不相同。

相关文章

网友评论

    本文标题:0x01.犀牛ch1-3

    本文链接:https://www.haomeiwen.com/subject/kosqlftx.html