面向对象的JavaScript基本知识指南大全(1)(3)
继承
在这篇文章中,我使用“类”这个术语极其宽松。如前所述,JavaScript没有类实体,但是后面仍可以跟类的模式。JavaScript与其他面向对象语言的区别主要在于继承模型。C++和Java体现了基于类的继承或传统继承。另一方面,JavaScript体现了原型继承(Prototypal Inheritance)。在其他面向对象语言中,类是一个实际的数据类型,表示创建对象的蓝图。在JavaScript中,虽然我们可以使用函数来模拟对象蓝图,但是它们实际上本身就是对象。然后,这些对象用作其他对象的模型(又叫原型),可以参阅文章《JavaScript原型继承》(http://www.webreference.com/programming/javascript/prototypal_inheritance/index.html)。
运用原型继承这个概念让我们得以创建“子类”,即继承另一个对象的属性的对象。如果我们想使用另一个对象的稍有一些变动的方法,这就变得极其有用。
以类Employee(员工)为例。假设我们有两种类型的员工:一种基于薪水,一种基于佣金。这些员工类型会有许多相似的属性。比如说,不管某员工通过佣金获得收入还是通过薪水获得收入,该员工都有名称。不过,对基于佣金的员工和基于薪水的员工来说,收入方式完全不一样。下面这个例子体现了这个概念:
- function Worker()
- {
- this.getMethods = function(properties, scope)
- {
- var $this = scope; //将类范围存储到名为$this的变量中
- //迭代处理对象的属性
- for ( var i in properties )
- {
- (function(i)
- {
- // 动态创建访问器方法
- $this[ "get" + i ] = function()
- {
- return properties[i];
- };
- //动态地创建一个分析整数,并确保是正值的更改器方法。
- $this[ "set" + i ] = function(val)
- {
- if(isNaN(val))
- {
- properties[i] = val;
- }
- else
- {
- properties[i] = Math.abs(val);
- }
- };
- })(i);
- }
- };
- }
- // CommissionWorker "子类"和WageWorker "子类"
- //继承Worker的属性和方法。
- CommissionWorker.prototype = new Worker();
- WageWorker.prototype = new Worker();
- function CommissionWorker(properties)
- {
- this.getMethods(properties, this);
- //计算收入
- this.getIncome = function()
- {
- return properties.Sales * properties.Commission;
- }
- }
- //要求有下列属性:薪水、每周小时数、每年周数
- function WageWorker(properties)
- {
- this.getMethods(properties, this);
- //计算收入
- this.getIncome = function()
- {
- return properties.Wage * properties.HoursPerWeek * properties.WeeksPerYear;
- }
- }
- var worker = new WageWorker(
- {
- Name: "Bob",
- Wage: 10,
- HoursPerWeek: 40,
- WeeksPerYear: 48
- });
- alert(worker.wage); //未定义。薪水是私有属性。
- worker.setWage(20);
- alert(worker.getName()); //输出 "Bob"
- alert(worker.getIncome()); //输出 38,400 (20*40*48)
- var worker2 = new CommissionWorker(
- {
- Name: "Sue",
- Commission: .2,
- Sales: 40000
- });
- alert(worker2.getName()); //输出 "Sue"
- alert(worker2.getIncome()); //输出8000(2% 乘40,000)
前一个例子中最重要的两个语句是:
- CommissionWorker.prototype = new Worker();
- WageWorker.prototype = new Worker();
这声明,对新的CommissionWorker或新的WageWorker对象的每个实例而言,Worker的属性和方法将传递到那些新对象。如果需要的话,这些方法和属性可以在“子类”定义里面被覆盖写入。
范围
JavaScript体现了所谓的函数范围。这意味着,函数中声明的变量在函数(变量来自该函数)外面最初是无法访问的。不过,在语句块中(如条件语句),可以对调用环境进行变量声明或改动。
- var car = "Toyota";
- if(car == "Toyota")
- {
- car = "Toyota - We never stop...and you won't either.";
- }
- alert(car); //输出Toyota——我们从未停上,你也如此。
- car = "Toyota"; //将汽车设回成原始值。
- function makeFord(car)
- {
- car = "Ford";
- }
- makeFord(car);
- alert(car); //输出"Toyota",因为汽车在函数范围中已改动。
不过,如果你想要改动值的函数,可以将对象作为参数来传递,并改动对象的属性。
- var car = new Object();
- car.brand = "Toyota"
- function makeFord(car)
- {
- car.brand = "Ford";
- }
- makeFord(car);
- alert(car.brand); //输出“Ford”
这名为“通过调用”传递,将值传递给函数。只有你在类里面创建方法,又知道对象含有什么属性,我一般才会建议采用通过调用传递。
现在你已经掌握了运用到JavaScript的面向对象的基本知识。运用这些原则,就可以为你在将来的开发项目简化代码。
原文:http://www.1stwebdesigner.com/design/object-oriented-basics-javascript/