1. 对象
对象是JavaScript的基础。JavaScript的大部分功能都是基于对象的。从最基本的层次而言,对象是一系列属性的集合。
// 创建一个新的Object对象,存放在 'obj' 变量中 var obj = new Object(); // 给这个对象设置一个属性 obj.val = 5; obj.click = function(){ alert( "hello" ); }; // 简写方式,键值对(key/value pair)来定义属性 var obj = { // 用键值对(key/value pairs)方式来设置属性名和属性值 val: 5, click: function(){ alert( "hello" ); } };
2. 对象的创建
和大部分的其它面向对象的语言不同,JavaScript并没有类(class)的概念。其它面向对象语言大多需要实例化某个具体的类。但JavaScript不同,JavaScript里对象本身可以用来创建新对象,而对象也可以继承自其它对象。这个概念称为原型化继承(prototypal inheritance)。
不管JavaScript使用何种对象方案,首先还是应该有一个创建新对象的方法。JavaScript的做法是,任何函数都可以被实例化为一个对象。
// 一个简单的函数,接受名称并将其存入当前上下文中 function User( name ) { this.name = name; } // 指定名称来创建该函数的一个新对象 var me = new User( "My Name" ); // 设置了它的name属性 alert( me.name == "My Name" ); // User对象的一个实例 alert( me.constructor == User ); // 既然User只是个函数,如果只把它作为函数来使用它呢? User( "Test" ); // this指向默认的全局 window 对象 alert( window.name == "Test" );
constructor 属性在每个对象中都存在,并一直指向创建它的函数。这样就可以有效地复制对象,用同一个基类创建对象并赋予不同的属性。
// 创建一个新的简单的User对象 function User() {} // 创建一个User对象 var me = new User(); // 用前一个对象的 constructor 引用来创建对象 var you = new me.constructor(); // 这两个对象的 constructor 实质上是一致的 alert( me.constructor == you.constructor );
3. 公共方法
公共方法(public method)在对象的上下文中是最终用户始终可以接触到的。要实现这种在对象的每个实例都可以使用的公共方法。必须了解 prototype(原型)的属性,这个属性包含一个对象,该对象可以作为所有新副本的基引用(base reference)。本质上说,所有对象原型的属性都能在该对象的每个实例中找到。
因为对象的原型仍然是对象,和其他任何对象一样,可以给它添加新的属性。给原型添加属性的结果是由该原型实例化的每个对象都会获得这些属性,也就使这些属性公有化了。
// 创建一个新的User构造函数 function User( name, age ){ this.name = name; this.age = age; } // 将一个新函数加到对象的 prototype 对象中 User.prototype.getName = function(){ return this.name; }; // 再次给 prototype 对象添加一个函数 User.prototype.getAge = function(){ return this.age; }; // 实例化一个新的User对象 var user = new User( "Bob", 44 ); // 添加的这两个属性都在刚才创建的对象中,并且有合适的上下文 alert( user.getName() == "Bob" ); alert( user.getAge() == 44 );
4. 私有方法
私有方法(private method)和私有变量只允许其他的私有方法、私有变量和特权方法访问。这种方法可以定义一些只让对象内部访问,而外部访问不到的代码。
// 表示教室的一个对象构造函数 function Classroom( students, teacher ) { // 用于显示班级所有学生的私有方法 function disp() { alert( this.names.join(", ") ); } // 将班级数据存入公共属性中 this.students = students; this.teacher = teacher; // 调用私有方法来显示错误 disp(); } // 创建一个新的 classroom 对象 var class = new Classroom( [ "John", "Bob" ], "Mr. Smith" ); // 调用 disp 方法会失败,因为它不是该对象的公共方法 class.disp();
5. 特权方法
特权方法(privileged method)是私有方法和公共方法的混合体。用来指代那些在查看并处理对象中私有变量的同时允许用户以公共方法的方法访问的方法。
// 创建一个新的User对象构造函数 function User( name, age ) { // 计算用户出生的年份 var year = (new Date()).getFullYear() - year; // 创建一个新的特权方法,能够访问 year 变量,同时自身属于公共的 this.getYearBorn = function(){ return year; }; } // 创建 User 对象的一个新实例 var user = new User( "Bob", 44 ); // 验证返回的年份 alert( user.getYearBorn() == 1980 ); // 无法访问对象的私有属性 alert( user.year == null );
本质上,特权方法是动态生成的,因为它们是在运行时才添加到对象中的,而不是代码在第一次编译时就已经生成的。虽然这个方法比在对象的prototype上绑定一个简单方法开销更大,但功能也更强大、更灵活。
// 创建一个新的User对象,接受一个有许多属性的对象作为参数 function User( properties ) { // 遍历该对象的所有属性,并保证其作用域正确 for ( var i in properties ) { (function(){ // 创建此属性的一个新的读取器(getter) this[ "get" + i ] = function() { return properties[i]; }; // 创建此属性的一个新的设置器(setter) this[ "set" + i ] = function(val) { properties[i] = val; }; })(); } } // 创建一个新的 User 对象实例 var user = new User({ name: "Bob", age: 44 }); // name 属性并不存在 // 它是属性对象(property object)的私有变量 alert( user.name == null ); // 可以使用 getname() 方法来获得这个值 // 因为它是动态生成的 alert( user.getname() == "Bob" ); // 可以通过新生成的函数来设置或获得年龄 user.setage( 22 ); alert( user.getage() == 22 );
6. 静态方法
静态方法与其它一般函数没有什么不同,最主要的区别是,作为一个属性,静态方法不能在该对象的实例的上下文中访问,而只属于主对象本身的上下文。静态方法的优点是保证对象的命名空间整洁,仅为组织代码而使用的方法
// 添加到一个 User 对象的静态方法 User.cloneUser = function( user ) { // 创建并返回一个新的 User 对象 return new User( user.getName(), user.getAge() ); };
转载请注明:陈童的博客 » JavaScript的语言特性 — 面向对象基础