JavaScript(03): 面向对象

来源:互联网 发布:淘宝如何分销 编辑:程序博客网 时间:2024/04/29 15:22

面向对象的开发方式是目前软件开发的主流方式,JavaScript也是面向对象事件驱动的编程语言,如果能够掌握JavaScript的面向对象编程的知识,就有了构建自己的JavaScript库的基础和前提。

1. 面向对象的基本概念

对于熟悉Java或者C#的开发者来说,面向对象的概念以及封装、继承、多态等名词应该是不陌生的。ECMAScript并没有正式的类,对象定义存放在一个函数——构造函数中。在JavaScript中构造函数与普通函数相比并没有什么特殊之处。

在ECMAScript中,对象由特性(attribute)构成,特性可以是原始值,也可以是引用值,如果特性存放的是函数,可以将其视为对象的方法(method),其他的视为对象的属性(property)。

2. 对象的创建和使用

对象的创建和销毁都在JavaScript执行过程中发生。对象是用关键字new后跟要实例化的类名创建的。

var obj = new Object();var str = new String();

ECMAScript定义了垃圾回收机制,意味着不用专门销毁对象来释放内存。当一个对象不被引用时,该对象就被废除了,而垃圾回收器的运行会导致废除的对象被销毁。将对象的引用设置为null可以废除该对象。对于那些旧的浏览器,由于没有完全的垃圾回收机制,所以可能出现对象不能被正确销毁的情况,废除对象和它的所有特性是确保内存使用正确的最好方法。

3. 对象的类型

  • 本地对象:独立于宿主环境的ECMAScript实现提供的对象。包括:Object、Function、Array、String、Boolean、Number、Date、RegExp、Error等。
    • Array类:
      • var x = new Array(); x[0] = "red"; x[1] = "blue"; x[2] = "green";
      • var y = new Array(20);
      • var z = new Array("red", "green", "blue");
      • 数组最多可以存放4294967295(2的32次方减1),可以满足大多数程序设计的需要。
      • 数组具有length属性、split()、slice()、concat()等方法。
      • ECMAScript的Array类一个非常有意思的地方是它提供的方法使数组的行为与其他数据类型的行为相似。例如,将Array对象当做栈(stack)来使用,通过push()和pop()方法进行存取操作。同时也可以通过shift()和unshift()方法将数组当做队列(queue)进行操作。
      • 数组提供了sort()方法可以对其进行排序操作,同时还提供了reverse()方法对数组进行倒转。
    • Date类:
      • 与Java中的Date类非常类似
  • 内置对象:由ECMAScript实现提供的独立于宿主环境的所有对象。
    • Global对象:Global对象是ECMAScript中最特别的对象,它不能被直接访问或调用,但是ECMAScript中不存在独立的函数,所有函数都必须是某个对象的方法。因此我们之前提到的isNaN()、isFinite()、parseInt()、parseFloat()等都是Global对象的方法。除此之外,encodeURI()和encodeURIComponent()方法用于编码传递给浏览器的URI(例如要将空格编码成%20);当然与此对应有decodeURI()和decodeURIComponent()方法。最后,也是最强大的一个方法eval(),该方法就像整个ECMAScript的解释程序,接受要执行的JavaScript字符串。这种功能非常强大,不过也非常危险,存在被代码注入的可能性。
    • Math对象:提供了数学函数(不解释)
  • 宿主对象:所有BOM和DOM对象都是宿主对象(依赖于浏览器环境的对象,因此不可避免的会牵扯到浏览器兼容性问题)


4. 定义类或对象

  • 工厂方式
    • function createCar() {    var temp = new Object;    temp.color = "red";    temp.brand = "Benz";    temp.drive = function() {        alert(this.brand + " is running...");    }    return temp;}var car = createCar();car.drive();


  • 构造器方式
    • function Car(brand, color) {if(this instanceof Car) {this.brand = brand;this.color = color;this.drive = function() {alert(this.brand + " is running...");};}}var car = new Car("Benz", "black");car.drive();


  • 原型方式
    • function Car() {}Car.prototype.brand = "Benz";Car.prototype.color = "black";Car.prototype.drive = function() {alert(this.brand + " is running...");}var car = new Car();car.drive();


5. 继承

1. 继承的概念

继承使得一个类可以重用另一个类的方法和属性,同时对已有的类的功能进行扩展。

2. 继承的方式

  • 对象冒充
    • function Person(name) {this.name = name;this.eat = function(place) {alert(this.name + " is eating at " + place);};}function Student(name, id) {this.newMethod = Person;this.newMethod(name);delete this.newMethod;this.id = id;this.study = function() {alert(this.name + " is studying...");};}var p1 = new Person("LUO Hao");var p2 = new Student("LIAO Qiang", 1234);p1.eat("Jinjiang Hotel");p2.eat("1st Dinning Hall");p2.study();


  • call()方法
    • function Person(name) {this.name = name;this.eat = function(place) {alert(this.name + " is eating at " + place);};}function Student(name, id) {Person.call(this, name);this.id = id;this.study = function() {alert(this.name + " is studying...");};}var p1 = new Person("LUO Hao");var p2 = new Student("LIAO Qiang", 1234);p1.eat("Jinjiang Hotel");p2.eat("1st Dinning Hall");p2.study();


  • apply()方法
    • function Person(name) {this.name = name;this.eat = function(place) {alert(this.name + " is eating at " + place);};}function Student(name, id) {Person.apply(this, arguments); // 2nd parameter is an arraythis.id = id;this.study = function() {alert(this.name + " is studying...");};}var p1 = new Person("LUO Hao");var p2 = new Student("LIAO Qiang", 1234);p1.eat("Jinjiang Hotel");p2.eat("1st Dinning Hall");p2.study();


  • 原型链
    • function Person(name) {this.name = name;this.eat = function(place) {alert(this.name + " is eating at " + place);};}function Student() {this.name = name;this.id = id;this.study = function() {alert(this.name + " is studying...");};}Student.prototype = new Person(this.name);Student.prototype.constructor = Student;var p1 = new Person("LUO Hao");var p2 = new Student("LIAO Qiang", 1234);p1.eat("Jinjiang Hotel");p2.eat("1st Dinning Hall");p2.study();


既然提到了继承,就再看看多态(polymorphism)的例子:

  • function ParentClass() {this.foo = function() {alert("This is common");}this.method = function() {alert("parent-class method");}}// just the same as static method of a classSubClass1.goo = function() {alert("gogo1");}SubClass2.goo = function() {alert("gogo2");}function SubClass1() {this.method = function() {alert("sub-class1 method");}}function SubClass2() {this.method = function() {alert("sub-class2 method");}}SubClass1.prototype = new ParentClass();SubClass1.prototype.constructor = SubClass1;SubClass2.prototype = new ParentClass();SubClass2.prototype.constructor = SubClass2; var o1 = new SubClass1();var o2 = new SubClass2();var array = new Array(2);array.push(o1);array.push(o2);for(var y in array) {if(array[y] instanceof SubClass1) {SubClass1.goo();// like static method}else if(array[y] instanceof SubClass2) {SubClass2.goo();}array[y].foo();array[y].method();//polymorphism method}