版权声明:本文由山茶树和葡萄树摘抄自《JavaScript 启示录》,作者: Cody Lindley;转载请说明出处。
JavaScript 启示录 附录
附录A回顾
对象是由存储值的已命名属性组成的。
JavaScript 中的几乎所有对象都可以表现得像对象。复杂值是对象,原始值可以看做对象。这就是为什么会听到有人说 JavaScript 中的所有对象都是对象。
对象是通过使用 new 关键字调用构造函数或者通过使用字面量表达式来创建的。
构造函数是对象(Function() 对象),因此,在 JavaScript 中,对象创建对象。
JavaScript 提供 9 个原生构造函数: Object()、Array()、String()、Number()、Boolean()、Function()、Date()、RegExp() 和 Error()。在需要时候,String()、Number() 和 Boolean() 构造函数可以提供原始值和对象包装器,以便原始值被当作对象时,它们可以表现得像对象。
null、undefined、”string”、10、true 和 false 值都是原始值,没有对象特性,除非将它们看做对象。
使用 new 关键字调用 Object()、Array()、String()、Number()、Boolean()、Function()、Date()、RegExp() 和 Error() 构造函数时,会创建一个对象,它被称为“复杂对象”或“引用对象”。
原始形式的 “string”、10、true 和 false 值没有对象的特性,除非把它们用作对象,然后,JavaScript 会在后台创建临时包装器对象,这种值就可以表现得像对象。
原始值是通过值存储的,复制时是通过字面进行复制的。另一方面,复杂对象值是通过引用进行存储的,复制时是通过引用进行复制的。
由于复杂对象和引用的特性,JavaScript 对象具有动态属性。
JavaScript 是可变的,这意味着可以在任何时间操作原生对象和用户自定义的对象属性。
可以使用点表示法或括号表示法获取、设置、更新对象的属性。当被操作的对象属性的名称采用表达式形式时,使用括号表示法非常方便[如
Array['prototype']['join'].apply()
]。当查找对象属性时,查找链首先查看对象引用的属性;如果没找到,则继续在构造函数的 prototype 属性上进行查找;如果仍找不到,由于原型拥有一个对象值并且该值是由 Object() 构造函数创建的,因此在 Object() 构造函数的 prototype 属性(
Object.prototype
)上进行查找。如果还找不到,那么可以确定该属性值为 undefined。原型查找链表明了继承(也称为原型继承)在 JavaScript 中是如何实现的。
由于对象属性查找链(也称为原型继承)在存在,因此所有对象都继承自 Object(),因为 prototype 属性本身就是一个 Object() 对象。
JavaScript 函数是一等公民:函数是拥有属性和值的对象。
在函数内部使用 this 关键字时,它是一种用于引用包含该函数的对象的通用方法。
在全局作用域内使用 this 关键字时,this 引用全局对象。
JavaScript 将函数作为创建唯一作用域的方法。
JavaScript 提供全局作用域,所有 JavaScript 代码都在这个作用域内。
函数(特别是封装函数)创建一个作用域链来解决变量查找问题。
作用域链是基于代码的编写方式创建的,而不是基于调用函数所有的上下文。这使得函数即使从一个不同的上下文调用函数,也能够访问最初编写代码时所在的作用域,这被称为闭包。
函数内部定义的函数表达式和变量,如果没有使用 var 声明,则都会变成全局属性。然而,函数作用域内部的函数语句仍在编写代码时所在的作用域内定义。
全局作用域内定义的函数和变量(没有使用 var),会成为全局对象的属性。
全局作用域内定义的函数和变量(使用 var),会成为全局变量。
附录B总结
JavaScript 语言精粹,Douglas Crockford
JavaScript 模式,Stoyan Stefanov
JavaScript 面向对象编程指南,Stoyan Stefanov
JavaScript 高级程序设计,Nicholas C.Zakas
高性能 JavaScript,Nicholas C.Zakas
章节节选
章节6.3
this 在函数内部引用包含函数的对象,其值基于在运行时调用函数的上下文,而不是函数本身[使用 new 关键字或
call()/apply()
的情况例外];章节1.4,使用 new 关键字时,this 值的字面意思是基于构造函数内部的语句创建的新对象/新实例。
ES3 中当 this 值的宿主函数被封装在另一个函数的内部或在另一个函数的上下文中被调用时,this 值将永远是对 Head对象(浏览器中的 window 对象)的引用,this 在 ES5 中是固定的。
章节7.1
在 JavaScript 中,作用域是执行代码的上下文。
包含函数的函数,会创建堆栈执行作用域,这些链接在一起的栈通常被称为作用域链。
JavaScript 没有块作用域。
章节7.7
作用域链是根据函数定义时的位置(位置体系、分层体系)确定的,而不是在调用时确定。这也叫做词法作用域。
闭包是由作用域链引起的。
章节8.1
prototype 属性是 JavaScript 为每个 Function() 实例创建的一个对象。
将通过 new 关键字创建的对象实例,链接回创建它们的构造函数,因此,共享和继承通用方法和属性。
其它延伸 1
词法作用域(lexical scope)等同于静态作用域(static scope)。所谓的词法作用域其实是指作用域在词法解析阶段既确定了,不会改变。
动态作用域(dynamic binding)是在运行时确定的,eval 和 with 可以产生动态作用域的效果。
词法作用域的函数中遇到既不是形参也不是函数内部定义的局部变量的变量时,在函数定义时的环境中查询。
动态域的函数中遇到既不是形参也不是函数内部定义的局部变量的变量时,到函数调用时的环境中查。