面向对象语言需要向开发者提供四种基本能力
在ECMAScript中,对象由特性attribute构成的,特性可以是原始值,也可以是引用值。
如果特性存在的是函数,它将被看作对象的方法method,否则该特性被看作属性property。
对象是用关键字new后面跟着要实例化的类的名字创建的:
var object = new Object();PS:创建了Object类的一个实例,并把这个实例存储在变量object中。
如果构造函数没有参数,括号则不是必须的
var object = new Object;
在ECMAScript中,不能访问对象的物理表示,只能访问对象的引用,所以每次创建对象,存储在变量中的都是该对象的引用,而不是对象本身。
由于ECMAScript是无用存储单元收集程序,意味着不必专门消耗对象来释放内存。当再没有对对象的引用时候,称为该对象被废除dereference了。
方式:把对象的所有引用都设置成null,可以强制性的废除对象。
var object = new Object; // do something with the object here object = null;PS: 废除对象的所有引用的时候需要小心,如果一个对象有两个或者更多的引用,则要正确的废除该对象,必须将其所有引用都设置成null.
所谓绑定binding,即把对象的接口与对象实例结合在一起的方法。
早绑定 early binding 指的是实例化对象之前定义他的特性和方法,这样编译器或者解释程序就能提前转换机器语言。像java这样的语言就是早绑定。而ECMAScript不是强类型语言,所以不支持早绑定。
晚绑定 late binding 使用晚绑定,无需检查对象的类型,只需要检查对象是否支持特性和方法即可。ECMAScript中的所有变量都是采用晚绑定方法。
所谓本地对象native object:独立于宿主环境的ECMAScript实现提供的对象。
Object/Function/Array/String/Boolean/Number/Date/RegExp/Error/EvalError/RangeError/ReferenceError/SyntaxError/TypeError/UrlError
所谓内置对象built-in object ,由ECMAScript实现提供的,独立于宿主环境的所有变量,在ECMAScript程序开始执行时出现。
Global对象是ECMAScript中最特别的对象,因为实际上它根本不存在。
这里需要理解的是:在ECMAScript中,不存在独立的函数,所有函数都必须是某个对象的方法。
所以像isNaN(),isFinite(),parseInt(),parseFloat()方法都是Global对象的方法。
小结Global对象的方法:
encodeURI()/encodeURIComponent()/decodeURI()/decodeURIComponent()/eval()/isNaN()/isFinite()/parseInt()/parseFloat()
Math对象提供了很多方法用于计算。这里先略了。有机会详细的拉出一节来总结。
所有非本地对象都是宿主对象host object,所有DOM和BOM都是宿主对象。
对于公用和受保护,私有作用域对于ECMAScript都是没有意义的,因为在ECMAScript中只存在一种作用域-公用作用域。在ECMAScript中所有对象的所有属性和方法都是公用的。
网上人的建议对象私有作用域使用下划线来定义:
obj._color = 'red';
在java中类是可以拥有静态属性和方法的,无需在实例化该类的对象,既可以访问这些属性和方法。
严格的来说,ECMAScript中是没有静态作用域的,不过可以给构造函数提供属性和方法
PS:构造函数只是函数,函数是对象,对象可以拥有属性和方法的。
对于关键字this:总是指向调用该方法的对象。
使用预定义对象的能力只是面向对象语言的能力的一部分,它真正强大之处在于能够创建自己专用的类和对象。
/*
* 工厂方式
* */
function createCar(color, size, mpg) {
var oTempCar = {};
oTempCar.color = color;
oTempCar.size = size;
oTempCar.mpg = mpg;
oTempCar.getColor = function () {
console.log(this.color);
}
return oTempCar;
}
var oCar1 = createCar('red', 21, 33);
var oCar2 = createCar('blue', 11, 44);
oCar1.getColor();
oCar2.getColor();
/*
* 构造函数方式
* */
function Car(color, size, mpg) {
this.color = color;
this.size = size;
this.mpg = mpg;
this.getColor = function () {
console.log(this.color);
}
}
var oCar3 = new Car('green', 33, 22);
var oCar4 = new Car('white', 44, 66);
oCar3.getColor();
oCar4.getColor();
/*
* 原型方式
* */
function newCar() {
}
newCar.prototype.color = 'orange';
newCar.prototype.size = 22;
newCar.prototype.mpg = 32;
newCar.prototype.getColor = function () {
console.log(this.color);
}
var oCar5 = new newCar();
oCar5.getColor();
console.log(oCar5 instanceof newCar);
/*
* 混合的构造函数/原型方式
*
* 用构造函数定义对象的所有非函数属性。
* 用原型方式定义对象的函数属性(方法)
* */
function newCar2(color, size, mpg) {
this.color = color;
this.size = size;
this.mpg = mpg;
}
newCar2.prototype.getColor = function () {
console.log(this.color);
}
var oCar6 = new newCar2('black', 22, 99);
oCar6.getColor();
略,不建议使用
略,不建议使用
对于属性prototype,每个构造函数都有prototype属性,可以用于定于方法。
使用prototype属性为任何已有的类定义新的方法。
/*
输出十六进制的字符串
*/
String.prototype.toHexString = function(){
return this.toString(16);
}
使用属性prototype同样可以覆盖已有的方法。
Function.prototype.toString = function(){
return 'Function code hidden';
}