资讯专栏INFORMATION COLUMN

JS 面向对象(一)封装(抽象)

codercao / 690人阅读

摘要:面向对象的三大特点封装,继承,多态缺一不可。构造函数,是一种特殊的方法。特别的一个类可以有多个构造函数,可根据其参数个数的不同或参数类型的不同来区分它们即构造函数的重载。

一、基本概念和背景

面向对象程序设计(OOP:Object-oriented programming)是一种程序设计范型,同时也是一种程序开发的方法。对象指的是类的实例。
面向对象(Object Oriented,OO)是一种对现实世界理解和抽象的方法,是计算机编程技术[1] 发展到一定阶段后的产物。

面向对象的三大特点(封装,继承,多态)缺一不可。通常“基于对象”是使用对象,但是无法利用现有的对象模板产生新的对象类型,继而产生新的对象,也就是说“基于对象”没有继承的特点。而“多态”表示为运行时类型确定(父类类型的子类对象实例),动态绑定执行对象,没有了继承的概念也就无从谈论“多态”。
示例:绘制一个图形,图形已有为三角形、圆;
Java 示例

// 父类:抽象、封装
public class  Graph {
 void draw() {
  System.out.println("draw a Graph");
 }
}
// 继承:子类type1
public class Triangle extends Graph {
 @Override
 void draw() {
  System.out.println("draw a Triangle");
 }
}
 
// 继承:子类type2
public class Circle extends Graph {
 @Override
 void draw() {
  System.out.println("draw a Circle");
 }
}
// 多态:运行时类型确定
public class Drawer {
 static void draw(Graph a) {
  a.draw();
}

// 运行调用
public static void main(String args[]) {
  Graph p = new Triangle();
  Drawer.draw(p); // "draw a Triangle"
  p = new Circle();
  Drawer.draw(p); //"draw a Circle"
}

Javascript ES5示例

// 封装
function Graph(){}
Graph.prototype.draw = function (){
  console.log("draw a Graph");
}
// 原型链引用
function Trianggle(){}
Trianggle.prototype = new Graph();
Trianggle.prototype.draw =  function (){
  console.log("draw a Trianggle");
}
// 原型链引用
function Circle(){}
Circle.prototype = new Graph();
Circle.prototype.draw =  function (){
  console.log("draw a Circle");
}
// 相对多态:无显示对象类型
function Drawer(obj){
  obj.draw();
}
// 运行时类型确定
var p = new Trianggle();
Drawer(p);
p = new Circle();
Drawer(p); 

大多面向对象语言中,面向对象一般基于面向’类‘的设计。类是代码抽象的模式之一:实例化(instantiation)、继承(inheritance)、和 (相对)多态(polymorphism)。类和实例的关系好比房屋建造。建筑师会绘制建筑蓝图,建筑工人根据蓝图落地成实际建筑,建筑就是蓝图的复制(概念和物理上的复制)。类就是建筑的抽象,含有一个建筑的所有特性。实例就是实际的建筑,包含了门、窗以及实际材料、地理位置。类通过复制操作被实例化为对象形式,实例间无直接关系。但这无法直接对应到 JavaScript 的实现机制,因为 Javascript 没有实质类的概念,ES6的 class也是一种语法糖1

二、JavaScript 封装方法

面向对象编程强调的是数据和操作数据行为的的相互关联,因此最好的设计就是把数据和它相关的行为打包(封装)起来。
封装(Encapsulation)是指一种将抽象性函数式接口的实现细节部份包装、隐藏起来的方法

2.1 好处

(1) 良好的封装能降低耦合度
(2) 方面数据统一管理、对象内部结构灵活修改
(3) 对其成员有更精确的控制,易于扩展
(4) 隐藏实现信息、细节,只暴露需要的 API

2.2 封装模式(创建对象模式) 构造函数2 & 原型链

(1)工厂模式 - 函数 【内部对象创建属性方法并返回对象,使用this】

 function createPerson(name, age, job){
        var o = new Object();
        o.name = name;
        o.age = age;
        o.job = job;
        o.sayName = function(){
            alert(this.name);
        }
        return o;
 }
var person1 = createPerson(“John”, 18, “Teacher");
var person2 = createPerson(“Greg”, 30, “Doctor”);

(2) 构造函数模式【内部 this创建属性、方法;无 return; 通过改变 this指向创建实例】

**原生构造函数**:隐式创建对象,属性、方法赋值给 this对象,无 return;
function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function(){
        alert(this.name);
    }
}
var person1 = new Person(“John”, 18, “Teacher");
var person2 = new Person(“Greg”, 30, “Doctor”);

构造函数: new 显示创建 对象

步骤1: 创建一个新对象
步骤2:讲构造函数的作用是赋值给新对象 (this 只向新对象 词法作用域发生改变)
步骤3:执行构造函数的代码 (为新对象 添加属性 )
步骤4:返回新对象

function Person(name, age, job){
   this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function(){
        alert(this.name);
    }
}

构造函数作为函数; 问题:作用域改变,每个传入的对象重建一遍;)
var person1 = new Object();

 Person.call( person1, “John”, 18, “Teacher");

var person2 = new Person(“Greg”, 30, “Doctor”);

(3) 原型模式 【原型对象创建属性、方法】

   构造函数无传参, 共享原型对象的属性,其中一个实例对原型对象的引用类型属性做修改,影响所有其他实例对该属性的使用;
 (* 引用类型属性受影响  内存分配机制不同引起)
function Person(){}

Person.prototype.name =  "Nicholas";
Person.prototype.age = 27;
Person.prototype.job = "Doctor";
Person.prototype.friends =  ["Lily", "John", "Alex"]
Person.prototype.sayName = function() {
     console.log(this.name);
}
Person.prototype.getFriends = function() {
     console.log(this.friends);
}
 var person1 = new Person();
 person1.name = "person1";

 var person2 = new Person();
 person2.name = "person2";
 person2.sayName();  //“person2"
 person2.getFriends(); // ["Lily", "John", "Alex"]
 person1.friends.push(“Van");
 person1.sayName(); //“person1"
 person2.getFriends();  //["Lily", "John", "Alex", "Van"]

(4) 构造函数 & 原型模式结合 【构造函数独立属性方法,原型对象创建公用属性、方法】
好处:构造函数模式 定义实例个性化属性;原型模式定义方法和共享属性;功能模块化 职责单一

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = [‘Lily", "John", "Alex"];
}

Person.prototype ={
    constructor: Person,
      sayName: function(){
         alert(this.name);
     }
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
person1.friends.push("Van");
var person2 = new Person(“Greg", 27, "Doctor");

(5) 动态原型模式 (使用:功能模块化)【构造函数独立属性方法,原型对象按需创建公用属性、方法】

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = [‘Lily’, "John", "Alex"];
    
    if(typeof this.sayName != ‘function’){
            Person.prototype.sayName = function(){
                    alert(this.name);
            };
    }
}

(6) 寄生构造函数模式 -【 已有对象扩展 - 原型链 】 (使用:第三方库扩展 )

   1.写法上和工厂模式一样 调用时多加 new  
   2.此模式创建的对象 与构造函数无关系, instanceof操作符无意义
function  Person(name, age, job){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
        alert(this.name);
    }
    return o;
}
 // 工厂模式
// var person1 =  Person(“John”, 18, “Teacher”);
// 寄生模式
 var friend  =  new Person(“John”, 18, “Teacher”); // 返回新对象的实例

(7) 稳妥模式 【 内部建对象不用 this 闭包 - 词法作用域 】(稳妥对象-无公共属性,方法不引用 this)(使用:适用于安全环境 - 禁用 this 和 new)

 1.写法上和寄生模式类似 , 除方法不使用 this  
 2.此模式创建的对象 与构造函数无关系, instanceof操作符无意义
function  Person(name, age, job){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
        alert(name); //无 this
    }
    return o;
}
var friend = Person(“John”, 18, “Teacher”); //无 new
  • 类实质是对象复制的概念,JavaScript 则是一种对象委托引用的概念,对引用类型变量变更其[prototype]依然拥有共享功能。 ↩

  • 构造函数 ,是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。特别的一个类可以有多个构造函数 ,可根据其参数个数的不同或参数类型的不同来区分它们 即构造函数的重载。 ↩

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

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

    相关文章

    • 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
    • JS中的面向对象编程

      摘要:一面向对象编程面向对象编程是一种抽象方式创建模型的编程方式。继承我们实现一个子类,继承汽车类将类的属性和方法赋值给继承汽车类的原型链创建子类实例以上是中的面向对象编程的简单介绍,如有错误,欢迎指出。 一.面向对象编程面向对象编程(OOP--Object Oriented Programming)是一种抽象方式创建模型的编程方式。继承,封装,多态是OOP的三大基本特征。许多主流编程语言都...

      lunaticf 评论0 收藏0

    发表评论

    0条评论

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