栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > Web开发 > JavaScript

面向对象之封装性

JavaScript 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

面向对象之封装性

面向对象编程的三个特点

面向对象编程是比较符合人的认知思维的一种编程方式,比如提到机动车,我们会想到几个重要的属性:速度、轮子、载人等;还有几个重要的行为:加速、刹车、转弯等。
我们经常见到的出租车、救护车、公交车等都属于机动车的实际例子,如果执行“加速”,这些车都会增加前进的速度。
可以说,机动车属于具体实物中抽取出来共同的属性和行为,将其封装在一起,这在面向对象编程中称为封装性;而具体到出租车、救护车、公交车等,全部继承了机动车这些属性和行为,这在面向对象编程中称为继承性;同一个属性或行为,可能会产生不同的效果,比如公交车的载人量大于出租车,这在面向对象编程中称为多态性

封装性

将需要的属性(数据)和行为(对数据的操作,以下内容改称为方法)封装在一起,比如 Java 中“类”的概念,叫做面向对象的封装性。

封装方式

首先,按照惯例,如果类名使用字母,那么首字母大写;
其次,类的内容由两部分构成,属性与方法。如果将属性与方法看作类的成员,按照访问权限划分,分为类成员(也称静态成员,使用关键字 static 给予修饰)、实例成员与私有成员。

ES6 的类

ES6 引入了类的概念,语法比较接近传统面向对象语言。

例子:

class Person {
    //实例属性
    name = "Tom";
    id = "232321";
    //实例方法
    getName() {
 return this.name;
    }

    //私有属性(提案中,暂无浏览器支持)
    #age = 20;
    //私有方法(提案中,暂无浏览器支持)
    #getAge() {
 return this.#age;
    }

    //静态属性(提案中,Chrome80 测试通过)
    static job = "IT";
    //静态方法
    static getJob() {
 return this.job;
    }
}

ES6 并不是本系列手记的重点,因此了解即可。

ES5 的组合封装

ES5 的组合封装是指:通过为构造函数定义属性和方法创建静态成员,通过 this 与构造函数原型创建实例成员,通过函数作用域的特性创建私有成员。

例子:

function Person() {
    //实例属性
    this.name = "Tom";
    this.id = "232321";
    //实例方法
    Person.prototype.getName = function() {
 return this.name;
    };

    //私有属性
    var age = 20;
    //私有方法
    var getAge = function() {
 return this.age;
    };
}
//静态属性
Person.job = "IT";
//静态方法
Person.getJob = function() {
    return this.job;
};

私有成员在其继承者(1)中,都是不可访问的;而静态成员,是仅供构造函数本身使用的,不管有没有创建实例对象,都可以通过函数名直接访问。因此能够发生继承的,只有实例成员。
实例成员由两部分组成:第一部分是定义在 this 上的成员,可以供其继承者直接深度复制,相当于在继承者中直接声明一样,为了便于区分,习惯上称这类成员为实例属性(包括属性和方法);第二部分是构造函数原型中的成员,其继承者可以通过原型链访问到,属于所有继承者共有的,习惯上称这类成员为原型属性(包括属性和方法)。

*(1)继承者:子类以及实例对象。

例子:

function Person() {
    //实例属性
    this.name = "Tom";
    this.ids = [1, 2];
    Person.prototype.nums = [8, 9];
    //实例方法
    Person.prototype.getName = function() {
 return this.name;
    };

    //私有属性
    var age = 20;
    //私有方法
    var getAge = function() {
 return this.age;
    };
}
//静态属性
Person.job = "IT";
//静态方法
Person.getJob = function() {
    return this.job;
};


console.log(Person.job); //输出:IT
console.log(Person.getJob()); //输出:IT


var p = new Person();
console.log(p.age); //输出:undefined


console.log(p.name); //输出:Tom
console.log(p.getName()); //输出:Tom


var p1 = new Person();
console.log(Object.is(p.ids, p1.ids));
//输出 false,说明储存空间不同,属于复制


console.log(Object.is(p.nums, p1.nums));
//输出 true,说明储存空间相同,属于原型链查询
利用闭包访问私有成员

闭包是有权访问另一个函数作用域中变量的函数,利用这一点,我们能够创建访问私有成员的特权方法。

例子:

function Person() {
    //私有属性
    var age = 20;

    //特权方法
    this.getAge = function() {
 return age;
    };
    this.setAge = function(value) {
 age = value;
    };
};

var p = new Person();
p.setAge(18);
console.log(p.getAge()); //输出:18

甚至可以直接将闭包作为创建实例对象的构造函数。

例子:

var Person = (function() {
    //私有属性
    var age = 20;

    //构造函数
    return function() {
 this.getAge = function() {
     return age;
 };
 this.setAge = function(value) {
     age = value;
 };
    };
})();

var p = new Person();
p.setAge(18);
console.log(p.getAge()); //输出:18
安全检测

鉴于构造函数只有在 new 关键字的作用下才会生成实例对象,因此检测构造函数的调用方式变得尤为重要。instanceof 以及 ES6 引入的 new.target 属性都可以用来做此类的安全检测。

例子:

function Person() {
    if (this instanceof Person) { //或者 new.target === Person
 this.name = "Tom";
    } else {
 return new Person();
    }
}

var p1 = new Person();
var p2 = Person();

如此一来,即使忘记了使用 new 关键字,仍然可以正确地创建实例对象。


如有错误,欢迎指正,本人不胜感激。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/243925.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号