JavaScript权威指南笔记(1)

2018-12-29

JavaScript权威指南笔记(1)

以下是一些读书笔记:

如果一条语句以”(“、”[“、”/”、”+” 或”-”开始, 那么它极有可能和前一条语句合在一起解析。

  • 由于解释器的二义性原因,最好还是在每行代码后加一个分号,加分号又类不死人

对象的比较并非值的比较:即使两个对象包含同样的属性及相同的值,它们也是不相等的。

  • ”==“运算符和”===“运算符都是比较的引用,当然只有自己可以”等于”自己,和Java一样

做显式类型转换最简单的方法就是使用Boolean()、Number()、String()或Object()函数。

  • 这个和Java, C中有些不一样,所以记下来

如果”+”运算符的一个操作数是字符串,它将会把另外一个操作数转换为字符串。一元”+”运算符将其操作数转换为数字。

  • 特别是+更”青睐”字符串类型而不是数字

变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。

  • 主要是讲var声明的变量是函数作用域

JavaScript全局变量是全局对象的属性,这是在ECMAScript规范中强制规定的。

  • 这个和JS的作用域链实现有关

这个作用域链是一个对象列表或者链表,这组对象定义了这段代码”作用域中”的变量。当JavaScript需要查找变量x的值的时候(这个过程称做”变量解析”(variableresolution)),它会从链中的第一个对象开始查找,如果这个对象有一个名为x的属性,则会直接使用这个属性的值,如果第一个对象中不存在名为x的属性,JavaScript会继续查找链上的下一个对象。如果第二个对象依然没有名为x的属性,则会继续查找下一个对象,以此类推。如果作用域链上没有任何一个对象含有属性x,那么就认为这段代码的作用域链上不存在x,并最终抛出一个引用错误 在JavaScript的最顶层代码中(也就是不包含在任何函数定义内的代码),作用域链由一个全局对象组成。在不包含嵌套的函数体内,作用域链上有两个对象,第一个是定义函数参数和局部变量的对象,第二个是全局对象。在一个嵌套的函数体内,作用域链上至少有三个对象。理解对象链的创建规则是非常重要的。当定义一个函数时,它实际上保存一个作用域链。当调用这个函数时,它创建一个新的对象来存储它的局部变量,并将这个对象添加至保存的那个作用域链上,同时创建一个新的更长的表示函数调用作用域的”链”。对于嵌套函数来讲,事情变得更加有趣,每次调用外部函数时,内部函数又会重新定义一遍。因为每次调用外部函数的时候,作用域链都是不同的。内部函数在每次定义的时候都有微妙的差别——在每次调用外部函数时,内部函数的代码都是相同的,而且关联这段代码的作用域链也不相同。

  • 作用域链的描述。个人感觉这个概念就像C中用栈来模拟函数调用,而JS中使用了作用域链。作用是一样的,但JS这种实现更加符合动态语言的特点。但也造成了一些this对象的坑。因为this就是引用当前作用域链。

undefined是全局变量,和null不同,它不是一个关键字

  • undefined==null为true

属性名是通过运算得出的值而不是固定的值的时候,这时必须使用方括号写法

  • 这是一种比较骚的写法,也体现了动态语言的特性。

如果函数使用return语句给出一个返回值,那么这个返回值就是整个调用表达式的值。否则,调用表达式的值就是undefined。

  • 没有返回值是返回的undefined。这么设计我觉得也是挺好的。

JavaScript首先创建一个新的空对象,然后,JavaScript通过传入指定的参数并将这个新对象当做this的值来调用一个指定的函数。这个函数可以使用this来初始化这个新创建对象的属性。

  • 这段描述太深入了,让我感觉是在描述编译过程的语法制导。

如果其中一个操作数是字符串或者转换为字符串的对象,另外一个操作数将会转换为字符串,加法将进行字符串的连接操作。如果两个操作数都不是类字符串(string-like)的,那么都将进行算术加法运算。

  • 解释为什么在JS中,+是比较坑爹

”===“也称为严格相等运算符(strictequality)(有时也称做恒等运算符(identityoperator)),它用来检测两个操作数是否严格相等。”==“运算符称做相等运算符(equalityoperator),它用来检测两个操作数是否相等,这里”相等”的定义非常宽松,可以允许进行类型转换。

  • 区别

“!=“和”!==“运算符的检测规则是”==“和”===“运算符的求反

  • 是的

NaN和其他任何值都是不相等的,包括它本身。通过x!==x来判断x是否为NaN,只有在x为NaN的时候,这个表达式的值才为true。

  • 这是一个判断值是否为NaN的技巧,因为NaN==Nan也是false

如果一个值是null,另一个是undefined,则它们相等。

  • null==undefined

对象o中存在一个隐藏的成员,这个成员指向其父类的原型,如果父类的原型是另外一个类的实例的话,则这个原型对象中也存在一个隐藏成员指向另外一个类的原型,这种链条将许多对象或类串接起来,既是原型链。

  • 原型链的描述。是JS在语法上实现继承的方法。

关于eval()最重要的是,它使用了调用它的变量作用域环境。也就是说,它查找变量的值和定义新变量和函数的操作和局部作用域中的代码完全一样 并且事实上,eval的字符串执行时的上下文环境和调用函数的上下文环境是一样的,这不能使其作为函数的一部分来运行

  • 就是说eval()中的代码的环境是在调用它的作用域链中,会产生很坑的事。但我觉得似乎没有什么地方是不能避免使用eval()

如果var语句中的变量没有指定初始化表达式,那么这个变量的值初始为undefined。

  • 和Java中的0,C/Cpp中的真正的未初始化都不一样

操作数是null的时候,typeof将返回”object”。 所有可执行对象进行typeof运算都将返回”function”。

  • 关于typeof运算符的一些技巧

需要注意的是,删除属性或者删除数组元素不仅仅是设置了一个undefined的值。当删除一个属性时,这个属性将不再存在。读取一个不存在的属性将返回undefined,但是可以通过in运算符(见4.9.3节)来检测这个属性是否在对象中存在。

  • 关于in运算符的一些技巧