资讯专栏INFORMATION COLUMN

一起学习面向对象——封装

Neilyo / 3009人阅读

摘要:构造函数内部在构造函数内部通过用于指向当前对象变量添加属性或方法此处定义的属性和方法都是为对象自身所拥有每次通过类创建实例时指向的属性都会得到相应的创建私有属性只能被私有方法和特权方法访问私有方法在构造函数里声明能被私有函数特权方法访问只能

构造函数内部: tips:

在构造函数内部通过this(用于指向当前对象)变量添加属性或方法,
此处定义的属性和方法都是为对象自身所拥有,
每次通过类创建实例时, this指向的属性都会得到相应的创建.

var Person = function(name, sex) {
    // 私有属性: 只能被【私有方法】和【特权方法】访问
    var contact = "xxxxx@qq.com";
    var number = "88888888";

    // 私有方法: 在构造函数里声明, 能被【私有函数】【特权方法】访问, 只能访问【私有方法】和【私有属性】
    var getInfo = function(name, sex) {
        console.log("My name is " + name + ", I’m a " + sex + "!");
        console.log("My email is " + contact);
    };

    // 公有属性
    this.name = name;
    this.sex = sex;

    // 特权方法: 可以访问【私有属性】【私有方法】【公有属性】
    this.intro = function() {
        getInfo(name, sex);
    };
    this.getContact = function(number) {
        console.log(number);
    };

    // 构造器
    this.getContact(number);
};
构造函数外部: tips:

通过点语法定义的属性和方法不会添加到新创建的对象,因此类的实例无法访问, 只能通过类的自身(Person)访问.

// 类静态公有属性(对象不能访)
Person.isChinese = true;

// 类静态公有方法(对象不能访问到)
Person.speak = function() {
    console.log("what???");
};
类的原型: tips:

一种是为原型对象属性赋值, 另一种是将一个对象赋值给类的原型对象.
通过prototype继承的属性或方法是每个对象通过prototype访问到的,
所以每次通过类创建实例时, 这些属性和方法不会再次创建.

Person.prototype = {
    // 显示指定对象的constructor属性
    constructor: Person,
    // 公有属性
    hobby: "reading",
    // 公有方法
    sport: function() {
        console.log("run");
    }
};

// test:
var tony = new Person("Tony", "man", "25");

console.log("--- 访问【公有属性】 ---");
console.log(tony.name);            // Tony
console.log(tony.sex);            // man

console.log("--- 访问【特权方法】 ---");
console.log(tony.intro());        // My name is Tony, I’m a man!
                                // My email is xxxxx@qq.com

console.log("--- 访问【类静态公有属性】和【类静态公有方法】 ---");
console.log(tony.isChinese);     // undefined
console.log(tony.speak());        // undefined

console.log("--- 通过类自身访问【类静态公有属性】和【类静态公有方法】 ---");
console.log(Person.isChinese);    // true
console.log(Person.speak());    // what???

console.log("--- 访问【公有属性】及【公有方法】 ---");
console.log(tony.hobby);        // reading
console.log(tony.sport());        // run


// 通过闭包实现:
var Person = (function() {
    // 静态私有变量
    var isChinese = true;

    // 静态私有方法
    var speak = function() {};

    // 创建类
    var _person = function() {
        // 私有属性: 只能被【私有方法】和【特权方法】访问
        var contact = "xxxxx@qq.com";
        var number = "88888888";

        // 私有方法: 在构造函数里声明, 能被【私有函数】【特权方法】访问, 只能访问【私有方法】和【私有属性】
        var getInfo = function(name, sex) {
            console.log("My name is " + name + ", I’m a " + sex + "!");
            console.log("My email is " + contact);
        };

        // 公有属性
        this.name = name;
        this.sex = sex;

        // 特权方法: 可以访问
        this.intro = function() {
            getInfo(name, sex);
        };
        this.getContact = function(number) {
            console.log(number);
        };

        // 构造器
        this.getContact(number);
    };

    // 构建原型
    _person.prototype = {
        constructor: _person,
        // 公有属性
        hobby: "reading",
        // 公有方法
        sport: function() {
            console.log("run");
        }
    };

    // 返回类
    return _person;
})();
类的两种写法

标准原型写法

function Person() {}
Person.prototype.sayHi = function() {}

var me = new Person();
console.log(me.constructor === Person);    // true;

对象字面量

function Person() {}
Person.prototype = {
    sayHi: function() {}
}
var me = new Person();
console.log(me.constructor === Person);    // false;
console.log(me.constructor === Object);    // true;
使用对象字面量的缺点:

使用对象字面形式改写原型对象改变了构造函数的属性,因此它现在指向Object而不是Person.

原因:

因为原型对象具有一个constructor属性,这是其他对象实例所没有的.
当一个函数被创建时,它的prototype属性也被创建, 且该原型对象的constructor属性指向该函数.
当使用对象字面形式改写原型对象Person.prototype时, 其constructor属性将被置为泛用对象Object.

解决:

在改写原型对象时手动重置其constructor属性.

    // 对象字面量修正:
    function Person() {}
    Person.prototype = {
        constructor: Person,
        sayHi: function() {
            console.log("Hi~");
        }
    }
    var me = new Person();
    console.log(me.constructor === Person);    // true;
    console.log(me.constructor === Object);    // false;
创建对象的安全模式
var Person = function(name, sex) {
    this.name = name;
    this.sex = sex;
};

var tony = new Person("Tony", "boy");
console.log(tony.name);     // Tony
console.log(tony.sex);        // boy

var anna = Person("Anna", "girl");
console.log(window.name);     // Anna
console.log(window.sex);    // girl

console.log(anna);        // undefined
console.log(anna.name);        // Uncaught TypeError: Cannot read property "name" of undefined
tips:

new可以看作是对当前对象this不停地赋值,
如果没有new, 则会直接执行函数, 因为函数在全局作用域中执行了,
所以在全局作用域中this指向的当前对象就自然是全局变量,
属性都添加到window上面了;
另外一个则因为Person类中没有return语句,
则函数执行完没有返回执行结果. 所以实例对象为undefined;

// 创建对象的安全模式
var Person = function(name, sex) {
    // 判断执行过程中this是否是当前对象(如果是说明是用new创建的)
    if(this instanceof Person) {
        this.name = name;
        this.sex = sex;
    } else {
        // 否则重新创建这个对象
        return new Person(name, sex);
    }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80087.html

相关文章

  • 谈谈我所理解的面向对象

    摘要:众多面向对象的编程思想虽不尽一致,但是无论哪种面向对象编程语言都具有以下的共通功能。原型编程以类为中心的传统面向对象编程,是以类为基础生成新对象。而原型模式的面向对象编程语言没有类这样一个概念。 什么是面向对象?这个问题往往会问到刚毕业的新手or实习生上,也是往往作为一个技术面试的开头题。在这里我们不去谈如何答(fu)好(yan)问(guo)题(qu),仅谈谈我所理解的面向对象。 从历...

    avwu 评论0 收藏0
  • SegmentFault 技术周刊 Vol.32 - 七夕将至,你的“对象”还好吗?

    摘要:很多情况下,通常一个人类,即创建了一个具体的对象。对象就是数据,对象本身不包含方法。类是相似对象的描述,称为类的定义,是该类对象的蓝图或原型。在中,对象通过对类的实体化形成的对象。一类的对象抽取出来。注意中,对象一定是通过类的实例化来的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 马上就要到七夕了,离年底老妈老爸...

    李昌杰 评论0 收藏0
  • SegmentFault 技术周刊 Vol.32 - 七夕将至,你的“对象”还好吗?

    摘要:很多情况下,通常一个人类,即创建了一个具体的对象。对象就是数据,对象本身不包含方法。类是相似对象的描述,称为类的定义,是该类对象的蓝图或原型。在中,对象通过对类的实体化形成的对象。一类的对象抽取出来。注意中,对象一定是通过类的实例化来的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 马上就要到七夕了,离年底老妈老爸...

    Lyux 评论0 收藏0
  • SegmentFault 技术周刊 Vol.32 - 七夕将至,你的“对象”还好吗?

    摘要:很多情况下,通常一个人类,即创建了一个具体的对象。对象就是数据,对象本身不包含方法。类是相似对象的描述,称为类的定义,是该类对象的蓝图或原型。在中,对象通过对类的实体化形成的对象。一类的对象抽取出来。注意中,对象一定是通过类的实例化来的。 showImg(https://segmentfault.com/img/bVTJ3H?w=900&h=385); 马上就要到七夕了,离年底老妈老爸...

    AaronYuan 评论0 收藏0
  • 一起学习面向对象——继承

    摘要:缺陷在子类构造函数中执行了一遍父类构造函数,在实现子类原型的类式继承时又调用了一遍父类构造函数,因此调用了两遍构造函数。 类式继承 原理 类的原型对象的作用就是为类的原型添加公有属性和公有方法,但类不能直接访问这些属性和方法,必须通过原型prototype来访问。而我们实例化一个父类的时候,新创建的对象复制了父类的构造函数内的属性与方法,并且将原型__proto__指向了父类的原型对象...

    MycLambert 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<