2012年8月19日星期日

Javascript 面向对象编程(来源:http://coolshell.cn/articles/6441.html)

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.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']

�������Щ���ӣ����ǿ��Կ�������㣺

  1. Javascript����ݺͳ�Ա��װ�ܼ򵥡�û������ȫ�Ƕ������������̬��
  2. Javascript function�е�thisָ��ܹؼ����û�еĻ����Ǿ��Ǿֲ�������ֲ�����
  3. Javascript�����Ա���������ʹ��ʱ��ʱ����������һ��ȫ�ֺ���ֱ�Ӹ���ȥ�ͺ��ˡ�
  4. Javascript�ij�Ա���������ʵ���Ͻ����޸ģ�Ҳ����˵��ͬʵ����ͬ���������Ϊ��һ��һ��

�������� – 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��get��+1�ˣ�;

�����ٿ�һ����Ϊʵ�õ�����——�������е�����(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;
                }
            }
);
 
alert(chenhao.birth_year);
chenhao.birth_year = 2000;
alert(chenhao.age);

�����������е��鷳����˵����Ϊʲô��д������������ӣ�

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var chenhao = {
    name: "Chen Hao",
    email: "haoel@hotmail.com",
    website: "http://coolshell.cn",
    age: 100,
    get birth_year() {
        var d = new Date();
        var y = d.getFullYear();
        return ( y - this.age );
    },
    set birth_year(year) {
        var d = new Date();
        var y = d.getFullYear();
        this.age = y - year;
    }
 
};
alert(chenhao.birth_year);
chenhao.birth_year = 2000;
alert(chenhao.age);

�ǵģ����ȷ��������ģ�����ͨ��defineProperty()����Ը���Щ�£�
1�������� writable��configurable��enumerable ��������������á�
2����̬��Ϊһ����������ԡ����磺һЩHTML��DOM����

�鿴������������

���鿴������������Щ���ã������и�������������������Ժ����õȶ�����

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//����������.
function listProperties(obj)
{
    var newLine = "<br />";
    var names = Object.getOwnPropertyNames(obj);
    for (var i = 0; i < names.length; i++) {
        var prop = names[i];
        document.write(prop + newLine);
 
        // �г�������������ã�descriptor������getOwnPropertyDescriptor����
        var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
        for (var attr in descriptor) {
            document.write("..." + attr + ': ' + descriptor[attr]);
            document.write(newLine);
        }
        document.write(newLine);
    }
}
 
listProperties(chenhao);

call��apply�� bind �� this

����Javascript��thisָ�룬��C++/Java�����ơ� ����������ʾ�����ʾ��ܼ��ˣ��ҾͲ���˵�ˣ�

1
2
3
4
5
6
7
8
9
10
11
12
13
function print(text){
    document.write(this.value + ' - ' + text+ '<br>');
}
 
var a = {value: 10, print : print};
var b = {value: 20, print : print};
 
print('hello');// this => global, output "undefined - hello"
 
a.print('a');// this => a, output "10 - a"
b.print('b'); // this => b, output "20 - b"
 
a['print']('a'); // this => a, output "10 - a"

������������call �� apply������������IJ����Dz�������Ӳ�һ����һ���������ܲ�һ��apply������Ҫ��ܶࡣ���������ܣ��ɵ� JSPerf ��ȥ���ܿ�����

1
2
3
4
5
print.call(a, 'a'); // this => a, output "10 - a"
print.call(b, 'b'); // this => b, output "20 - b"
 
print.apply(a, ['a']); // this => a, output "10 - a"
print.apply(b, ['b']); // this => b, output "20 - b"

������bind��thisָ�룬���ܻ��в�һ������ΪJavascript�Ƕ�̬�ġ��������ʾ��

1
2
3
4
var p = print.bind(a);
p('a');             // this => a, output "10 - a"
p.call(b, 'b');     // this => a, output "10 - b"
p.apply(b, ['b']);  // this => a, output "10 - b"

�̳� �� ����

ͨ���������Щʾ�����ǿ���ͨ��Object.create()��ʵ�ʼ̳У��뿴����Ĵ��룬Student�̳���Object��

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
var Person = Object.create(null);
 
Object.defineProperties
(
    Person,
    {
        'name'  : {  value: 'Chen Hao'},
        'email'  : { value : 'haoel@hotmail.com'},
        'website': { value: 'http://coolshell.cn'}
    }
);
 
Person.sayHello = function () {
    var hello = "<p>Hello, I am "+ this.name  + ", <br>" +
                "my email is: " + this.email + ", <br>" +
                "my website is: " + this.website;
    document.write(hello + "<br>");
}
 
var Student = Object.create(Person);
Student.no = "1234567"; //ѧ��
Student.dept = "Computer Science"; //ϵ
 
//ʹ��Person������
document.write(Student.name + ' ' + Student.email + ' ' + Student.website +'<br>');
 
//ʹ��Person�ķ���
Student.sayHello();
 
//����SayHello����
Student.sayHello = function (person) {
    var hello = "<p>Hello, I am "+ this.name  + ", <br>" +
                "my email is: " + this.email + ", <br>" +
                "my website is: " + this.website + ", <br>" +
                "my student no is: " + this. no + ", <br>" +
                "my departent is: " + this. dept;
    document.write(hello + '<br>');
}
//�ٴε���
Student.sayHello();
 
//�鿴Student�����ԣ�ֻ�� no �� dept �� �����˵�sayHello��
document.write('<p>' + Object.keys(Student) + '<br>');

ͨ���������ʾ�����ǿ��Կ�����Person������Բ�û�б������Ƶ���Student�������������ǿ���ȥ��ȡ��������ΪJavascript��ί��ʵ������һ���ơ���ʵ�������Prototype��Person��Student��Prototype��

�����ǵĴ�����Ҫһ�����Ե�ʱ��Javascript��������ȿ���ǰ������������Ƿ���������ԣ����û�еĻ����ͻ�������Prototype�����Ƿ���������ԣ�һֱ������ȥ��ֱ���ҵ�����ֱ��û��Prototype����

Ϊ��֤������£����ǿ���ʹ��Object.getPrototypeOf()������һ�£�

1
2
3
4
5
6
7
Student.name = 'aaa';
 
//��� aaa
document.write('<p>' + Student.name + '</p>');
 
//��� Chen Hao
document.write('<p>' +Object.getPrototypeOf(Student).name + '</p>');

���ǣ��㻹�������Ӷ���ĺ�������ø�����ĺ���ͺ���C++��� Base::func() һ�����ǣ���������hello�ķ����Ϳ���ʹ�ø���Ĵ����ˣ�������ʾ��

1
2
3
4
5
6
7
//�°������SayHello����
Student.sayHello = function (person) {
    Object.getPrototypeOf(this).sayHello.call(this);
    var hello = "my student no is: " + this. no + ", <br>" +
                "my departent is: " + this. dept;
    document.write(hello + '<br>');
}

�����ǿ��ɡ�

���

������Ǹ������������������ǵ�Ҫ�����ǿ���ϣ����Щ��������������������ΪʲôҪ��ϣ���Ϊ���Ƕ�֪��������OO��Ƶ�����Ҫ�Ķ��������������Javascript����û��֧�ֵ��ر�ã�����������Ȼ���Ը㶨���¡�

���ȣ�������Ҫ����һ��Composition�ĺ���target���������Ƕ���source��Դ���󣩣�����������뻹�Ǻܼ򵥵ģ����ǰ�source�������һ��һ���ó���Ȼ���嵽target�С�

1
2
3
4
5
6
7
8
9
10
11
12
13
function Composition(target, source)
{
    var desc  = Object.getOwnPropertyDescriptor;
    var prop  = Object.getOwnPropertyNames;
    var def_prop = Object.defineProperty;
 
    prop(source).forEach(
        function(key) {
            def_prop(target, key, desc(source, key))
        }
    )
    return target;
}

������������Ժ����ǾͿ����������ˣ�

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//������
var Artist = Object.create(null);
Artist.sing = function() {
    return this.name + ' starts singing...';
}
Artist.paint = function() {
    return this.name + ' starts painting...';
}
 
//�˶�Ա
var Sporter = Object.create(null);
Sporter.run = function() {
    return this.name + ' starts running...';
}
Sporter.swim = function() {
    return this.name + ' starts swimming...';
}
 
Composition(Person, Artist);
document.write(Person.sing() + '<br>');
document.write(Person.paint() + '<br>');
 
Composition(Person, Sporter);
document.write(Person.run() + '<br>');
document.write(Person.swim() + '<br>');
 
//���� Person����ʲô���������sayHello,sing,paint,swim,run��
document.write('<p>' + Object.keys(Person) + '<br>');

Prototype �� �̳�

��������˵˵Prototype�������ȿ��������̣������̲���Ҫ���Ͱɣ�����C������ĺ���ָ�룬��C����������Ķ�����ö��ˡ�

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var plus = function(x,y){
    document.write( x + ' + ' + y + ' = ' + (x+y) + '<br>');
    return x + y;
};
 
var minus = function(x,y){
    document.write(x + ' - ' + y + ' = ' + (x-y) + '<br>');
    return x - y;
};
 
var operations = {
    '+': plus,
    '-': minus
};
 
var calculate = function(x, y, operation){
    return operations[operation](x, y);
};
 
calculate(12, 4, '+');
calculate(24, 3, '-');

��ô�������ܲ��ܰ���Щ������װ�����أ�������Ҫʹ��prototype���������ʾ��