最近阅读了《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"
原始值的复制操作是真实值复制;比较操作采用值比较。 示例:
代码语言:javascript复制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:
代码语言:javascript复制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)
代码语言:javascript复制var obj1 = new Object('foo');
var obj2 = new Object(function(){});
(2)
代码语言:javascript复制var add = new Function('param1', 'param2', 'return param1 param2');
var sub = new Function('param1, param2', 'return param1 - param2');
2. 函数
函数的定义有三种不同的方式:构造函数、函数语句和函数表达式。
代码语言:javascript复制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
代码语言:javascript复制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将在原型链中进行搜索。
代码语言:javascript复制var ary = ['foo','bar'];
ary.join(); //原型链:Array.prototype
ary.toLocalString(); //原型链:Object.prototype
1. 默认的prototype属性是Object()对象
示例:
代码语言:javascript复制var myFun = function(){}
console.log(myFun.prototype); //firefox:Object {} chrome:myFun {}
console.log(typeof myFun.prototype); //Object
2. 原型是一个对象,原型链将每个实例都链接至其构造函数的prototype属性。这意味任何使用new关键字(或原始值创建对象)创建对象时,它都会在“创建的对象实例”和“创建对象的构造函数”的prototype属性之间添加一个隐藏的链接。该链接在实例中被称为__proto__。
示例:
代码语言:javascript复制Array.prototype.foo = 'foo';
var ary = [];
ary.__proto__.foo; //结果:"foo"
注意:__proto__不是官方ECMA标准的一部分;构造函数属性可用于跟踪从对象到它继承的原型对象的链接! 示例:
代码语言:javascript复制Array.prototype.bar = 'bar';
var arr = new Array();
console.log(arr.constructor.prototype.bar); //结果:"bar"
console.log(arr.bar); //结果:"bar" bar对象上没有,从继承的原型上获取
3. 用新对象替换prototype属性会删除默认构造函数属性
示例:
代码语言:javascript复制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属性,应重新连接引用该构造函数的构造函数属性。
示例:
代码语言:javascript复制var Bar = function Bar(){};
Bar.prototype = {constructor : Bar };
var BarInstance = new Bar();
console.log(BarInstance.constructor); //结果:Bar()
4. 用新对象替换prototype属性不会更新以前的实例
示例:
代码语言:javascript复制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)的结构