Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【JavaScript】面向对象之封装 #36

Open
Tracked by #6
swiftwind0405 opened this issue Apr 4, 2020 · 0 comments
Open
Tracked by #6

【JavaScript】面向对象之封装 #36

swiftwind0405 opened this issue Apr 4, 2020 · 0 comments

Comments

@swiftwind0405
Copy link
Owner

swiftwind0405 commented Apr 4, 2020

把客观事物封装成抽象的类,隐藏属性和方法,仅对外公开接口。

ES6 之前的封装

ES6 的 class 实际是一个语法糖,在 ES6 之前,是没有类这个概念的,因此是借助于原型对象构造函数来实现。

function Person(sex) {
  var heart = "heart" // 私有属性
  var laugh = function() {
    // 私有方法
    console.log("ha...ha...");
  }

  this.sex = sex // 公有属性
  this.heartbeat = function() {
    // 公有方法
    console.log(heart + " beat");
  }
}

Person.prototype.home = "earth" //公有属性
Person.prototype.jump = function() {
  // 公有方法
  this.heartbeat();
  console.log("jump");
}

Person.core = "brain" //静态属性
Person.talk = function() {
  // 静态方法
  console.log("bla...bla...");
}

var man = new Person("male");

私有属性、公有属性、静态属性概念:

  • 私有属性和方法:只能在构造函数内访问不能被外部所访问(在构造函数内使用 var 声明的属性)
  • 公有属性和方法(或实例方法):对象外可以访问到对象内的属性和方法(在构造函数内使用 this 设置,或者设置在构造函数原型对象上比如 Person.prototype.xxx)
  • 静态属性和方法:定义在构造函数上的方法(比如 Person.xxx),不需要实例就可以调用(例如 Object.assign())

实例对象上的属性和构造函数原型上的属性:

  • 定义在构造函数原型对象上的属性和方法虽然不能直接表现在实例对象上,但是实例对象却可以访问或者调用它们。
  • 当访问一个对象的属性 / 方法时,它不仅仅在该对象上查找,还会查找该对象的原型,以及该对象的原型的原型,一层一层向上查找,直到找到一个名字匹配的属性 / 方法或到达原型链的末尾(null)。

遍历实例对象属性的三种方法:

  • 使用 for...in... 能获取到实例对象自身的属性和原型链上的属性使用
  • Object.keys()Object.getOwnPropertyNames() 只能获取实例对象自身的属性可以通过 .hasOwnProperty() 方法传入属性名来判断一个属性是不是实例自身的属性

ES6 之后的封装

在 ES6 之后,新增了 class 这个关键字。它可以用来代替构造函数,达到创建“一类实例”的效果。并且类的数据类型就是函数,所以用法上和构造函数很像,直接用 new 命令来配合它创建一个实例。

类的所有方法都定义在类的prototype属性上面:

class Cat {    
	constructor() {}    
	toString () {}    
	toValue () {}
}

// 等同于
function Cat () {}
Cat.prototype = {    
	constructor() {}    
	toString () {}    
	toValue () {}
}

将上面 ES5 的例子转化成 ES6:

class Person {
  constructor(sex) {
    var heart = "heart"; // 私有属性
	// 严格意义上并不是私有属性,只不过被局限于constructor这个构造函数中,是这个作用域下的变量而已
    var laugh = function() {
      // 私有方法
      console.log("ha...ha...");
    }

    this.sex = sex // 公有属性
    this.heartbeat = function() {
      // 公有方法
      console.log(heart + " beat");
    }
  }
  jump () {
    // 公有方法 等同于 Person.prototype.jump = function() {}
    this.heartbeat();
    console.log("jump");
  }
  home = "earth"; // 公有属性 等同于在constructor中 this.home = 'earth'
  static core = "brain" // 静态属性 等同于 Person.core = 'brain'
  static talk = function() {
    // 静态方法
    console.log("bla...bla...");
  }
}

var man = new Person("male");

class的基本概念:

  • 当你使用class的时候,它会默认调用constructor这个函数,来接收一些参数,并构造出一个新的实例对象(this)并将它返回。
  • 如果你的class没有定义constructor,也会隐式生成一个constructor方法

class中几种定义属性的区别:

  1. constructorvar一个变量,它只存在于constructor这个构造函数中
  2. constructor中使用this定义的属性和方法会被定义到实例上
  3. class中使用=来定义一个属性和方法,效果与第二点相同,会被定义到实例上
  4. class中直接定义一个方法,会被添加到原型对象prototype
  5. class中使用了static修饰符定义的属性和方法被认为是静态的,被添加到类本身,不会添加到实例上

other:

  • class本质虽然是个函数,但是并不会像函数一样提升至作用域最顶层
  • 如遇class中箭头函数等题目请参照构造函数来处理
  • 使用class生成的实例对象,也会有沿着原型链查找的功能
  • class 类内部所有定义的方法不可枚举
  • class 类不能重写 prototype 属性(writable 默认为 false)
  • class 类默认使用严格模式

参考资料

@swiftwind0405 swiftwind0405 changed the title 【Day36】【JavaScript】面向对象之封装 【Day19】【JavaScript】面向对象之封装 Apr 4, 2020
@swiftwind0405 swiftwind0405 changed the title 【Day19】【JavaScript】面向对象之封装 【JavaScript】面向对象之封装 Apr 29, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant