js面向对象基础
程序1. 创建简单对象并设置其属性的两个例子
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
2 var obj = new Object();
3 //将该对象的一些属性设置成不同的值
4 obj.val = 5;
5 obj.click = function(){
6 alert( "hello" );
7 };
8 //下面是等效的代码,使用了{...}式缩写,
9 //和定义对象属性的"名称-值"对
10 var obj = {
11 //用名称-值对设置对象属性
12 val: 5,
13 click: function(){
14 alert( "hello" );
15 }
16 };
实际上对象就这么回事了。然而,事情变得麻烦的地方,在于新对象(尤其是那些继承其它对象属性的对象)的创建。
不像大多数其它面向对象的语言,JavaScript实际上并没有类的概念。在大多数其它的面向对象语言中,你可以初始化一个特定的类的实例,但是在JavaScript中的情况这是这样。在JavaScript中,对象能够创建新的对象,对象可以继承自其它对象。整个概念被称为"prototypal inheritance"(原型标本继承)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
2 //并将其保存于当前上下文中
3 function User( name ) {
4 this.name = name;
5 }
6 //用指定的name创建上述函数的新实例
7 var me = new User( "My Name" );
8 //我们可以看到name已经被成为对象本身的属性
9 alert( me.name == "My Name" );
10 //而且它确实是User对象的一个新实例
11 alert( me.constructor == User );
12 //那么,既然User()只是一个函数,
13 //当我们这么处理它的时候,发生了什么?
14 User( "Test" );
15 //因为this上下文没有被设置,它缺省地指向全局的window对象,
16 //这意味着window.name将等于我们提供给它的那个name
17 alert( window.name == "Test" );
公有方法
公有方法可以完全地被对象的上下文中的最终使用者访问。为了实现这些对于特定对象的所有实例都可用的公共方法,你需要学习一个名为"prototype"的属性。prototype 简单地包含一个对象,为一个父对象的所有新副本充当对基类的引用。本质上,prototype 的任何属性对该对象的所每一个实例都是可用的。创建/引用的过程给了我们一个廉价版的继承
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
2 function User( name, age ){
3 this.name = name;
4 this.age = age;
5 }
6 //为prototype对象添加一个新方法
7 User.prototype.getName = function(){
8 return this.name;
9 };
10 //为prototype对象添加另一个方法
11 //注意此方法的上下文将是被实例化的对象
12 User.prototype.getAge = function(){
13 return this.age;
14 };
15 //实例化一个新的User对象
16 var user = new User( "Bob", 44 );
17 //我们可以看到两个方法被附加到了对象上,有着正确的上下文
18 alert( user.getName() == "Bob" );
19 alert( user.getAge() == 44 );
私有方法
私有方法和变量只能被其它的私有方法、私有变量的特权方法访问。这是一种定义只能在内象内部访问的代码的方式。
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
2 function Classroom( students, teacher ) {
3 //用来显示教室中的所有学生的私有方法
4 function disp() {
5 alert( this.names.join(", ") );
6 }
7 //课程的数据存储在公有的对象属性里
8 this.students = students;
9 this.teacher = teacher;
10 //调用私有方法显示错误
11 disp();
12 }
13 //创建一新的教室对象
14 var class = new Classroom( [ "John", "Bob" ], "Mr. Smith" );
15 //失败,因为disp不是该对象的公有方法
16 class.disp();
尽管很简单,私有方法却是非常重要的,它可以在保持你的代码免于冲突同时允许对你的用户可见和可用的施以更强大的控制。接下来,我们来研究特权方法。它是你的对象中可以使用的私有方法和共有方法的联合。
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
2 function User( name, age ) {
3 //计算用户的出生年份
4 var year = (new Date()).getFullYear() – age;
5 //创建一个新特权方法,对变量year有访问权,
6 //但又是公共可访问的
7 this.getYearBorn = function(){
8 return year;
9 };
10 }
11 //创建一个User对象的新实例
12 var user = new User( "Bob", 44 );
13 //验证返回的出生年份是否正确
14 alert( user.getYearBorn() == 1962 );
15 //并注意我们不能访问对象的私有属性year
16 alert( user.year == null );
本质上,特权方法是动态生成的方法,因为它们是在运行时而不是代码初次编译时添加给对象的。这种技术在计算量上要比绑定一个简单的方法到对象的prototype 上来得昂贵,但同时也的强大和灵活得多。
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
2 //创建一个新的接受properties对象的对象
3 function User( properties ) {
4 //遍历对象属性,确保它作用域正确(如前所述)
5 for ( var i in properties ) { (function(which){ var p=i
6 //为属性创建获取器
7 which[ "get" + i ] = function() {
8 return properties[p];
9 };
10 //为属性创建设置器
11 which[ "set" + i ] = function(val) {
12 properties[p] = val;
13 };
14 })(this); }
15 }
16 //创建一个新user 对象实例,传入一个包含属性的对象作为种子
17 var user = new User({
18 name: "Bob",
19 age: 44
20 });
21 //请注意name属性并不存在,因为它在properties 对象中,是私有的
22 alert( user.name == null );
23 //然而,我们能够使用用动态生成的方法getname 来访问它
24 alert( user.getname() == "Bob" );
25 //最后,我们能看到,通过新生成的动态方法设置和获取age 都是可以的
26 user.setage( 22 );
27 alert( user.getage() == 22 );
28 </script>
静态方法
静态方法背后的前提其实跟其它任何方法是一样的。然而,最主要的不同在于,这些方法作为对象的静态属性而存在。作为属性,它们在该对象的实例上下文中不可访问;它们只有在与主对象本身相同的上下文是可用的。这些与传统的类继承的相似点,使得他们有点像是静态的类方法。
2 User.cloneUser = function( user ) {
3 //创建并返回一个新的User对象
4 return new User(
5 //该对象是其它user对象的克隆
6 user.getName(),
7 user.getAge()
8 );
9 };