乐趣区

关于javascript:js设计模式一面向对象封装

前言

最近始终在看 typescript,次要的一个目标是为vue3.x 做筹备。3.x 版本尤雨溪大神采纳 typescript 重写底层,具体内容能够查看 [[译] 尤雨溪:Vue 3.0 打算 - 掘金](https://juejin.im/post/684490…)。在typescript 里,简直齐全采纳 ES6 语法,其中最为重要的还是 class 类的应用,学到这块就有点懵逼了。什么?继承还能够这样玩?什么共有公有什么派生类???我之前学了个假 js 吧???

于是回头来从新梳理学习一下面对对象编程,这一系列文章全副是基于 ES5 语法规定,别跟我说为啥不间接用 ES6,ES6 它最终也是编译成 ES5 运行。
小子只是个前端菜鸟,对编程还没有太深刻的理解,只是个代码搬运工。如果文章有什么谬误或者是了解上的谬误,还请指条明路,感激不尽。

这一系列将以面对对象三个个性 封装 继承 多态 为题进行解说,更好的了解面对对象编程。

面对过程编程和面对对象编程(OOP)

面对过程编程

面向过程就是剖析出解决问题所须要的步骤,而后用函数把这些步骤一步一步实现,应用的时候一个一个顺次调用就能够了。

面对对象编程

面对对象编程就是将你的需要形象成一个对象,针对这个对象剖析其特色和动作,这个对象咱们称之为

对象基础知识

对象了解

程序员常常会拿对象来开玩笑:没对象?本人 new 一个呗,要啥样都能够。那到底什么是对象呢?js 中有一个说法是 万物皆对象 对象就是能够领有属性和办法的一个汇合。人,是一个对象,他有吃饭睡觉的属性,有下班赚钱的办法。所有的所有都能够形象为一个对象,只不过每个对象都属于本人的属性和办法。

什么叫面对对象编程???在 js 中,有两种编程格调。面对过程编程 面对对象编程 ,咱们写轮播图写动画写页面,大部分都是 面对过程编程(反正我集体目前是这样)。

对象三大特色

封装 继承 多态

一个对象被创立,这两头产生什么 | new 关键字做了什么(面试题)

 1、创立一个新的对象,这个对象的类型是 `object`
 2、设置这个新的对象的外部、可拜访性和 [[prototype]] 属性为构造函数(指 prototype.construtor 所指向的构造函数)中设置的
 3、将步骤 1 新创建的对象作为 this 的上下文 
 4、果该函数没有返回对象,则返回 this。

原型和原型链

  • 原型

    JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象。咱们能够把所有对象实例须要共享的属性和办法间接定义在 prototype 对象上。这个对象的所有属性和办法,都会被构造函数的所领有。
    prototype 作为对象的外部属性,咱们个别通过实例化对象的 __proto__ 这个属性进行拜访。
    在原型对象中还有一个属性constructor,这个属性对应创立所有指向该原型的实例的构造函数

  • 原型链

    当咱们拜访对象的一个属性或办法时,它会先在对象本身中寻找,如果有则间接应用,如果没有则会去原型对象中寻找,如果找到则间接应用。如果没有则去原型的原型中寻找, 直到找到 Object 对象的原型,Object 对象的原型没有原型,如果在 Object 原型中仍然没有找到,则返回 null。

function Person(name, age) {
    this.name = name 
    this.age= age

    this.action = function () {alert('hello word')
    }

}
var p = new Person('尤雨溪', 18) // 实例化 Person 这个对象

console.log(p.name) // 尤雨溪

/*
他们之间的关系

    构造函数的原型 == 实例化 p.__proto__
    构造函数 == 构造函数原型的 constructor
*/

 console.log(Person.prototype === p.__proto__) // true

 console.log(Person.prototype.constructor === Person) // true

console.log(p.constructor === Person) // true

面对对象—封装

什么是封装

封装就是把客观事物封装成形象的类,暗藏属性和办法的实现细节,仅对外公开接口。也就是说,封装就是将属性和办法组成一个类的过程就称之为封装。

对象封装的几种模式

对象字面量

  • 长处:代码简略易懂
  • 毛病:创立多个对象会产生大量的代码,编写麻烦,且并没有实例与原型的概念

    // 创建对象
    var  Person = {
      name: "尤雨溪",
      age: "18",
    
      action : function() {alert('hello word!');
      }
    }
    Person.name
    Person.action()
    
    
    // 创立一个空对象 给空对象增加办法属性
    var Person = {}
    Person.name = '尤雨溪'
    Person.age=  18
    
    Person.action  = function() {alert('hello word!');
    }
    

工厂模式

  • 对象字面量的模式在创立多个对象的时候会产生大量代码,如果咱们把创立新对象、增加对象属性、返回对象的过程放到这个函数中,每次须要创建对象的时候调用函数即可。

    function createPerson(name, age) {var person = new Object();
    person.name = name;
    person.age = age;
    
    person.action= function() {alert('hello word!');
    };
    return person;
    }
    
    // 生成实例
    var p = createPerson('尤雨溪', 18);
    var p2 = createPerson('阮一峰',20)
    
    console.log(p.name)
    p.action()
  • 长处:防止创立大量对象时代码的臃肿
  • 毛病:p1 与 p2 之间没有内在联系

构造函数

所谓 ” 构造函数 ”,其实就是一个一般函数,然而外部应用了 this 变量。对构造函数应用 new 运算符,就能生成实例,并且 this 变量会绑定在实例对象上。

function Person(name, age) {
    // 通过 this 来增加属性办法
    this.name = name 
    this.age = age

    this.action = function () {alert('hello word')
    }
}
// 实例化对象
var p1 = new Person('尤雨溪', 18)
var p2 = new Person('阮一峰', 20)

下面咱们说过,通过 new 关键字实例化进去的对象,都会有一个 constructor 属性指向他们的构造函数

console.log(p1.constructor === Person)     // true
console.log(p2.constructor === Person)     // true
  • 长处:实例化对象和构造函数之间存在关联
  • 毛病:节约内存,构造函数中定义的办法名 action 一样,但实例化进去的对象名不一样,造成一个内存的节约。

原型模式

下面咱们说过,每个对象被实例化的时候,都会有一个原型 prototype 属性,这个属性是能够被其余对象继承的。所以咱们能够将对象共有的属性办法,放到原型上,这样每次通过 new 进去的对象,在构造函数中的办法被屡次创立。

function Person(name, age) {
    // 通过 this 来增加属性办法
    this.name = name 
    this.age = age
}

// 将独特领有的办法挂在到原型上
Person.prototype.action = function () {alert('hello wodr')
    }
// 实例化对象
var p1 = new Person('尤雨溪', 18)
var p2 = new Person('阮一峰', 20)

p1.action()
p2.action()

属性和办法的类型

通过原型模式咱们能够将办法属性间接放在原型上,所有的实例对象都能够拜访这个属性办法,咱们称为 私有办法 / 属性 。相熟 ES6 的敌人晓得,在用class 定义类的时候,咱们能够定义外面属性办法的类型。是爱护类型,还是公开类型,还是公有类型,不同类型之间是不能互相拜访的 。在 ES6 中咱们能够通过public 等关键字来定义,那咱们 ES5 是怎么辨别他们的一个类型呢?

我之前在学习面对对象这一块的时候没有太过留神这一块内容,当初咱们开发也很少留神到这一块内容。其实在疾速开发的期间,咱们很少留神到这些 javascrip 基础理论常识,更不足对原生 js 的了解。

在面向对象中,每个属性都有它的一个类型,能够分为 共有 公有 动态 三种。

共有属性和办法

从字面量上的意思了解,共有,就是所有对象都有的属性或办法。

function Person(name, age) {
    // 通过 this 来增加属性办法

    this.name = name  // 共有属性
    this.age = age        
}

// 将独特领有的办法挂在到原型上
Person.prototype.action = function () {  // 共有办法
    console.log(`${this.name}是干 ${this.job}的 `)
}
// 实例化对象
var p1 = new Person('尤雨溪', '程序员')

p1.action()

从下面代码能够看出,通过 this 增加的属性或者在原型上增加的属性和办法都是共有的

  • 调用规定:调用私有办法,咱们必须先实例化对象

公有属性和办法

公有属性的了解能够从函数的作用域登程,函数外部定义的变量在函数内部无法访问。咱们看上面栗子

function Person(name, job) {
    // 通过 this 来增加属性办法
    var name = name  // 公有属性
    var job = job

    function action () { // 公有办法
       console.log(`${name}是干 ${job}的 `)
    }
}
// 实例化对象
var p = new Person('尤雨溪',  '程序员')

console.log(p.name)       // undefined
p.action()   //  p.action is not a function 报错

当实例化创建对象的时候,通过 var 定义的局部变量是无奈在外界被拜访,他只能在构造函数外部进行应用,并且不能通过 this 拜访,咱们吧代码变动一下再看。

function Person(name, job) {
    // 通过 this 来增加属性办法
    var name = name  // 公有属性
    var job = job

    function action1 () { // 公有办法
       console.log(`${name}是干 ${job}的 `, '通过 this 调用')
    }
  
    function action2 () { // 公有办法
       console.log(`${name}是干 ${job}的 `, '在外部调用')
    }
    
    // 这样是不能调用的
    this.action1()
    this.name

    action()}
// 实例化对象
var p = new Person('尤雨溪',  '程序员')    // 尤雨溪是干程序员的 在外部调用


  • 调用规定:对象的公有办法和属性, 内部是不能够拜访的,只能在外部应用

特权办法

在函数外部通过 this 创立的属性和办法,在创建对象时,每个对象本身都会领有一份并且能够在内部能够拜访到。通过 this 创立的属性能够看作对象的共有属性,而通过 this 创立的办法岂但能够 拜访这些对象的共有属性办法,还能拜访本身的公有属性办法 ,被称之为 特权办法

function Person(name, job) {
    // 通过 this 来增加属性办法
    var name = name  // 公有属性
    this.job = job   // 共有属性

    this.action = function () { // 特权办法
        console.log(`${name}是干 ${this.job}的 `)
    }

}
// 实例化对象
var p = new Person('尤雨溪', '程序员')
console.log(p.name)
p.action()     // 尤雨溪是干程序员的
  • 调用规定:通过实例化,能够拜访共有属性办法和公有属性办法

动态属性和办法

共有属性办法和公有属性办法都用通过 new 创建对象能力拜访,而动态属性办法不须要通过 new 关键字创立,就能够间接拜访。


function Person(name, job) {
    var name = name  // 公有属性
    this.job = job   // 共有属性

    this.action = function () { // 特权办法
        console.log(`${name}是干 ${this.job}的 `)
    }

}
Person.attr = '动态属性'
Person.say = function () {console.log('大家好,我是静态方法')
}

console.log(Person.attr) // 动态属性
Person.say() // 大家好,我是静态方法

// 实例化对象
var p = new Person('尤雨溪', '程序员')
console.log(p.attr) // undefined
p.say()     // 报错
  • 调用规定:静态方法无需实例化对象,便能够调用,对象实例不能调用对象的静态方法,只能调用实例本身的动态属性和办法。

动态类

后面咱们说过,对象创立有好几种模式,那咱们通过字面量的模式创立的对象,它的类型时什么呢?对象字面量模式创立的对象增加的办法只能时动态属性和静态方法,而 蕴含动态属性和静态方法的类叫动态类

var person = {
    name: "尤雨溪",
    age: "18",

    action : function() {console.log('hello word!');
    }
}
person.attr = '我是动态属性'
person.say = function () {console.log('大家好,我是静态方法')
}

console.log(person.name)
person.action()

person.attr 
person.say()
  • 调用规定:不须要通过 new 创建对象

相干文章

[[译] 尤雨溪:Vue 3.0 打算 - 掘金](https://juejin.im/post/684490…)
js 面向过程编程与面向对象编程的区别
JS 面向对象编程之封装
Javascript 面向对象(共有办法,公有办法,特权办法,动态属性和办法,动态类) 示例解说

退出移动版