来源:陈皓
Javascript是一个类C的语言,它的面向对象的东西相对于C++/Java比较奇怪,但是其的确相当的强大,在Todd 同学的“对象的消息模型”一文中我们已经可以看到一些端倪了。这两天有个前同事总在问我Javascript面向对象的东西,所以,索性写篇文章让他看去吧,这里这篇文章主要想从一个整体的解度来说明一下Javascript的面向对象的编程。(成文比较仓促,应该有不准确或是有误的地方,请大家批评指正)
另,这篇文章主要基于 ECMAScript 5, 旨在介绍新技术。关于兼容性的东西,请看最后一节。
初探
我们知道Javascript中的变量定义基本如下:
1 2 3 |
var name = 'Chen Hao';; var email = 'haoel(@)hotmail.com'; var website = 'http://coolshell.cn'; |
如果要用对象来写的话,就是下面这个样子:
1 2 3 4 5 |
var chenhao = { name :'Chen Hao', email : 'haoel(@)hotmail.com', website : 'http://coolshell.cn' }; |
于是,我就可以这样访问:
1 2 3 4 5 6 7 8 9 |
//以成员的方式 chenhao.name; chenhao.email; chenhao.website; //以hash map的方式 chenhao["name"]; chenhao["email"]; chenhao["website"]; |
关于函数,我们知道Javascript的函数是这样的:
1 2 3 |
var doSomething = function(){ alert('Hello World.'); }; |
于是,我们可以这么干:
1 2 3 4 5 6 7 8 9 10 11 |
var sayHello = function(){ var hello = "Hello, I'm "+ this.name + ", my email is: " + this.email + ", my website is: " + this.website; alert(hello); }; //直接赋值,这里很像C/C++的函数指针 chenhao.Hello = sayHello; chenhao.Hello(); |
相信这些东西都比较简单,大家都明白了。 可以看到javascript对象函数是直接声明,直接赋值,直接就用了。runtime的动态语言。
还有一种比如规范的写法是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//我们可以看到, 其用function来做class。 var Person = function(name, email, website){ this.name = name; this.email = email; this.website = website; this.sayHello = function(){ var hello = "Hello, I'm "+ this.name + ", n" + "my email is: " + this.email + ", n" + "my website is: " + this.website; alert(hello); }; }; var chenhao = new Person("Chen Hao", "haoel@hotmail.com", "http://coolshell.cn"); chenhao.sayHello(); |
顺便说一下,要删除对象的属性,很简单:
1 |
delete chenhao['email'] |
上面的这些例子,我们可以看到这样几点:
Javascript的数据和成员封装很简单。
Javascript function中的this指针很关键,如果没有的话,那就是局部变量或局部函数。
Javascript对象成员函数可以在使用时临时声明,并把一个全局函数直接赋过去就好了。
Javascript的成员函数可以在实例上进行修改,也就是说不同的实例的同一个函数名的行为和实现不一样。
属性配置 – Object.defineProperty
先看下面的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
//创建对象 var chenhao = Object.create(null); //设置一个属性 Object.defineProperty( chenhao, 'name', { value: 'Chen Hao', writable: true, configurable: true, enumerable: true }); //设置多个属性 Object.defineProperties( chenhao, { 'email' : { value: 'haoel@hotmail.com', writable: true, configurable: true, enumerable: true }, 'website': { value: 'http://coolshell.cn', writable: true, configurable: true, enumerable: true } } ); |
下面就说说这些属性配置是什么意思。
▲writable:这个属性的值是否可以改。
▲configurable:这个属性的配置是否可以改。
▲enumerable:这个属性是否能在for…in循环中遍历出来或在Object.keys中列举出来。
▲value:属性值。
▲get()/set(_value):get和set访问器。
Get/Set 选择器
关于get/set访问器,它的意思就是用get/set来取代value(其不能和value一起使用),示例如下:
1 2 3 4 5 6 7 8 9 10 11 |
var age = 0; Object.defineProperty( chenhao, 'age', { get: function() {return age+1;}, set: function(value) {age = value;} enumerable : true, configurable : true } ); chenhao.age = 100; //调用set alert(chenhao.age); //调用get 输出101; |
我们再看一个更为实用的例子——利用已有的属性(age)通过get和set构造新的属性(birth_year):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
Object.defineProperty( chenhao, 'birth_year', { get: function() { var d = new Date(); var y = d.getFullYear(); return ( y - this.age ); }, set: function(year) { var d = new Date(); var y = d.getFullYear(); this.age = y - year; } } ); |