最近阅读了《JavaScript启示录》,一本很薄但是内容却很充实的书籍。展现了准确的JavaScript世界观,涉及对象、属性、复杂值、原始值、作用域、继承、this关键字、head对象等重要概念。

一、JavaScript对象

1. JavaScript预包装了9个原生对象构造函数:


Number()、String()、Boolean()、Object()、Array()、Function()、Date()、RegExp()、Error()


注意:Math是一个静态对象,它不是使用new运算符的构造函数。

2. 字面量语法与使用new操作符的效果相同。但是也有例外:Number()、String()、Boolean()

字符串、数字和布尔值使用字面量值时,只有在该值被视为对象的情况下才会创建实际的复杂对象。换句话说,在使用与构造函数有关的方法或者属性之前,一直使用原始数据类型。在这种情况下,JavaScript会在为字面量创建一个包装器对象,一边将该值视为一个对象。调用方法结束后,JavaScript即抛弃包装器对象,该值返回字面量类型。

3. 原始值:10、true、null、undefined、"123"


原始值的复制操作是真实值复制;比较操作采用值比较。

示例:

var myStr1 = "foo";
var myStr2 = myStr1;
var myStr3 = "foo";
console.log(myStr2 === myStr3); //结果:true

myStr1 = "test";
console.log(myStr1,myStr2); //结果:test foo

4. 复杂值:Object()、Array()、Function()、Date()、RegExp()、Error()

复杂值的复制操作是引用的复制,而不是实际值;比较操作采用引用比较。


示例1:

var obj1 = {name : "ligang"};
var obj2 = obj1;
var obj3 = {name : "ligang"};
console.log(obj1 === obj3); //false

obj1.age = 25;
console.log(obj1 === obj2); //true
console.log(obj1,obj2); //Object {name: "ligang", age: 25} Object {name: "ligang", age: 25}

obj1 = {name : "lg"}; //obj1指向新对象,和obj2不再指向同一个对象
console.log(obj1,obj2); //Object {name: "lg"} Object {name: "ligang", age: 25}

二、Object()、Funcation()

1. 下面几种方式不建议使用,了解可通过此种方式构造对象和函数即可!


(1)

var obj1 = new Object('foo');
var obj2 = new Object(function(){});

(2)

var add = new Function('param1', 'param2', 'return param1 + param2');
var sub = new Function('param1, param2', 'return param1 - param2');

2. 函数

函数的定义有三种不同的方式:构造函数、函数语句和函数表达式。


var addConstructor = new Function('x' ,'y' ,'return x + y');
function addStatement(x, y){ return x + y; }
var addExpression = function(x, y){ return x + y; };

3. 函数实参和形参的length

var myFun = function(x, y, z){
console.log(myFun.length); //形参个数:3
console.log(arguments.callee.length); //形参个数:3
console.log(arguments.length); //实参个数:2
}
myFun(1,2);

三、 在web浏览器中引用head对象

(1)引用赋予head对象的名称:globalObj = window;


(2)在全局作用域中使用this关键字:globalObj = this;


四、JavaScript原型

对象的继承,实际是继承原型链!--JavScript原型(你不知道的JavaScript)


对象不包含某属性时,JavaScript将在原型链中进行搜索。


var ary = ['foo','bar'];
ary.join(); //原型链:Array.prototype
ary.toLocalString(); //原型链:Object.prototype

1. 默认的prototype属性是Object()对象

示例:


var myFun = function(){}
console.log(myFun.prototype); //firefox:Object {} chrome:myFun {}
console.log(typeof myFun.prototype); //Object

2. 原型是一个对象,原型链将每个实例都链接至其构造函数的prototype属性。这意味任何使用new关键字(或原始值创建对象)创建对象时,它都会在“创建的对象实例”和“创建对象的构造函数”的prototype属性之间添加一个隐藏的链接。该链接在实例中被称为__proto__。

示例:


Array.prototype.foo = 'foo';
var ary = [];
ary.__proto__.foo; //结果:"foo"

注意:__proto__不是官方ECMA标准的一部分;构造函数属性可用于跟踪从对象到它继承的原型对象的链接!


示例:


Array.prototype.bar = 'bar';
var arr = new Array();
console.log(arr.constructor.prototype.bar); //结果:"bar"
console.log(arr.bar); //结果:"bar" bar对象上没有,从继承的原型上获取

3. 用新对象替换prototype属性会删除默认构造函数属性

示例:


var Foo = function Foo(){};
var FooInstance1 = new Foo();
console.log(FooInstance1.constructor); //结果:Foo()
Foo.prototype = {};
var FooInstance2 = new Foo();
console.log(FooInstance2.constructor); //结果:Object()

如果想要替换JavaScript设置的默认prototype属性,应重新连接引用该构造函数的构造函数属性。

示例:


var Bar = function Bar(){};
Bar.prototype = {constructor : Bar };
var BarInstance = new Bar();
console.log(BarInstance.constructor); //结果:Bar()

4. 用新对象替换prototype属性不会更新以前的实例

示例:


var MyFun = function myFun(){};
MyFun.prototype.x = 1;
var o1 = new MyFun();
MyFun.prototype = { x : 2}
var o2 = new MyFun();
console.log(o1.x); //结果:1
console.log(o2.x); //结果:2


Underscore.js:增强及扩展对象

Backbone.js:为复杂Javascript应用程序提供模型(models)、集合(collections)、视图(views)的结构