JavaScript面向对象编程(入门参考)

发布时间:2020-11-09编辑:脚本学堂
本文介绍下入门级的JavaScript面向对象编程的教程,通过实例学习下javascript面向编程的相关知识,有需要的朋友不妨作个参考。

查看对象属性配置

如果查看并管理对象的这些配置,下面有个程序可以输出对象的属性和配置等东西:
 

复制代码 代码示例:
//列出对象的属性.   
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 很类似。

来看个示例:
 

复制代码 代码示例:
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,这两个函数的差别就是参数的样子不一样,另一个就是性能不一样,apply 的性能要差很多。(关于性能,可到 JSPerf 上去跑跑看看)
 

复制代码 代码示例:
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 是动态的。如下面的示例
 

复制代码 代码示例:
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。
 

复制代码 代码示例:
var Person = Object.create(null);   
    
Object.defineProperties   
(   
    Person,   
    {   
        'name'  : {  value: 'Chen Hao'},   
        'email'  : { value : 'haoel@hotmail.com'},   
        'website': { value: 'http://www.jb200.com'}   
    }   
);   
    
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 ()来检验一下:
 

复制代码 代码示例:
Student.name = 'aaa';   
    
//输出 aaa   
document.write('<p>' + Student.name + '</p>');   
    
//输出 Chen Hao   
document.write('<p>' +Object.getPrototypeOf(Student).name + '</p>'); 

于是,还可以在子对象的函数里调用父对象的函数,就好像 C++ 里的 Base::func () 一样。
于是,重载 hello 的方法就可以使用父类的代码了,如下所示:
 

复制代码 代码示例:
//新版的重载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 中。
 

复制代码 代码示例:
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;   
}  
 

有了这个函数以后,就可以这来玩了:
 

复制代码 代码示例:
//艺术家   
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>');