javascript 中的面向对象实现 如何封装

javascript 是一门很灵活的语言,也是一门有缺陷的语言.

比如我们今天要谈的,如何用面向对象的手法来封装javascript ,javascript是没有类的概念的.

所以今天谈到的封装,其实就是用javascript的函数来实现的.

var People{
    name:’一介布衣’,
    age:’30'
};


这就是javascript中的一个对象,里面封装了2个属性.


实例化一个对象的实例 people

var people=new People();
console.log(people.name,people.age);  //一介布衣,30


如果我们需要在函数里返回一个对象,如下代码:

function CreatePeople(){
    return {
        name:’一介布衣’,
        age:’30'
    };
}


在代码中需要创建一个人的时候,我们需要调用 CreatePeople 即可,但是有一个问题,就是我们得到的都是同一个人 一介布衣,30岁.看来需要我们改造一个函数.

function CreatePeople(name,age){
    return {
        name:name,
        age:age
    }
}


这看上去貌似好多了.我们实例化2个对象.

var p1=new CreatePeople(‘张三’,19);
var p2=new CreatePeople(‘李四’,25);


我们知道javascript从object 到其他全局类都有一个prototype对象指向原型链.

但是,p1,p2 俩个对象貌似没有一点关系,虽然被同一个函数创建,但是CreatePeople 每次返回一个全新的对象,看似 p1,p2关系不大.

如果你接触过面向对象语言的编程,这时应该想到了构造函数,但是上面的 CreatePeople 函数怎么看都不是一个构造函数,我们也可以用javascript的函数来生成一个构造函数.

function CreatePeople(name,age){
    this.name=name;
    this.age=age;
}


this 和其他语言一样,也是一个指向实例的指针变量.

当用此构造函数创建对象的时候,this就指向新创建的对象,有一点需要记住,this取决调用函数作用域,而不是使用函数的作用域.


这样封装一下构造函数,生成的对象就比上面看上去顺眼多了.

2个属性指向了this实例指针,我们再来一个方法,去获取属性(也可以理解为私有变量)

function CreatePeople(name,age){
    this.name=name;
    this.age=age;
    this.getName=function(){
        return this.name;
    }
}


getName 方法很简单,就是返回对象中的 name 属性值.

实例化2个对象

var p1=new CreatePeople('张三',20);
var p2=new CreatePeople('李四',21);
console.log(p1.getName()) //张三
console.log(p2.getName()) //李四

这时感觉封装的高大上的感觉,其实我们没有发现,CreatePeople 构造函数中的 getName 函数干的活很简单,但是每次都在实例上创建一个这样的函数确实有点浪费内存了,我们看下面的代码.

console.log(p1.getName==p2.getName);  //false

返回false ,告诉我们 p1,p2 中的 getName 不是指向内存中的一个地址,我们为了节省内存,如何让CreatePeople 构建出来的对象,多有 getName 方法指向一个指针地址? 对,Object 的原型链上.

我们把这个方法定义在构造函数的原型链上,这样构造的新对象都会继承原型链上的这个方法,(具体的javascript中的继承我们单独开一篇博文来讨论)

function CreatePeople(name,age){
    this.name=name;
    this.age=age;
}

CreatePeople.prototype.getName=function(){
    return this.name;
}


var p1=new CreatePeople('张三',20);
var p2=new CreatePeople('李四',21);

console.log(p1.getName==p2.getName);  //true


可以看到p1 和 p2 对象都继承来自 CreatePeople 原型上的 getName 方法,而且所有对象的此方法指针都指向了一个地址.

这样,我们封装的目的就达到了.


回到顶部