美文网首页
重学前端(五)模拟类?

重学前端(五)模拟类?

作者: f1a94e9a1ea7 | 来源:发表于2019-02-17 10:23 被阅读0次

配合另一篇博文「对 JS 创建对象的一些记录」一起食用效果会更好

JS 本身是面向对象的,所以不需要模拟,但是因为它面向对象的方式和主流流派不太一样,所以可以理解为常说的「模拟面向对象」是「模拟基于类的面向对象」

ES6 提供了 class 关键表面上模拟类,但任然是基于原型运行。

什么是原型?

「照猫画虎」,这里的猫就是虎的原型,这就是用原型来描述对象。

而「基于类」的编程提倡使用一个关注分类和类之间关系开发模型(不是很明白这句话)。这类语言,是先有类,再从类去实例化一个对象,类与类之间又可能形成继承、组合等关系。

「基于原型」更提倡程序员去关注一系列对象实例的行为,而后才去关心如何将这些对象划分到最近的使用方式相似的原型对象(还不是很清楚两者之间的区别)。
是通过「复制」的方法创建新对象,实际就是创建一个全新的对象。

原型系统的两种实现思路:

  1. 使新对象持有一个原型的引用,并不是真的复制
  2. 深复制,然后两个对象没有关联

JS 是前者。

JS 的原型

  1. 如果所有对象都有私有字段[[prototype]],就是对象的原型。(我猜测这里的意思是:对象的 prototype 属性就是对象的原型(指向对象的原型对象),函数的 prototype 属性指向该函数的原型)
  2. 读一个属性,如果对象本身没有,则会继续访问对象的原型,直到原型为空或者找到为止。

ES6 提供了一系列内置函数,来访问操纵原型:

  1. Object.create,根据指定的原型对象创建新对象,原型可以是 null
  2. Object.getPrototypeOf,获得一个对象的原型
  3. Object.setPrototypeOf,设置一个对象的原型
// 一个 cat 对象
let cat = {
    say() {
        console.log("meow")
    },
    jump() {
        console.log('jump')
    }
}

// 在 cat 对象的基础上画了一个 tiger 对象
let tiger = Object.create(cat, {
    say: {
        writable: true,
        configurable: true,
        enumerable: true,
        value: function() {
            console.log('roar')
        }
    }
})
// cat 这个对象生出了一个具体的实例/对象
let anotherCat = Object.create(cat)
// 因为是 cat 生的,所以也有 cat 的 say 方法
anotherCat.say()

// 同上
let anotherTiger = Object.create(tiger)
anotherTiger.say()

以上是 ES6 的写法,早期版本是怎么写的呢?

早期版本的类与原型

类的定义是一个私有属性 [[class]],语言标准为内置类型例如 Number、String、Date 等指定了 [[class]] 属性,以表示它们的类,访问这个属性的方式是: Objecg.prototype.toString

    var o = new Object;
    var n = new Number;
    var s = new String;
    var b = new Boolean;
    var d = new Date;
    var arg = function(){ return arguments }();
    var r = new RegExp;
    var f = new Function;
    var arr = new Array;
    var e = new Error;
    console.log([o, n, s, b, d, arg, r, f, arr, e].map(v => Object.prototype.toString.call(v)));

ES5 后,[[class]] 私有属性被 Symbol.toStringTag 代替

var o = { [Symbol.toStringTag]: "MyObject" }
console.log(o + '') // [object MyObject]

上面隐性调用了 Object.prototype.toString
(这里不是特别明白,为什么 [Symbol.toStringTag] 这个属性会对结果产生影响)

new 操作做的事情:

  1. 以构造器的 prototype 属性(这里的构造器应是指构造函数,函数的 prototype 属性指向原型对象,对象的私有属性 proto 指向它的原型对象)为原型,创建新对象;
  2. 将 this 和调用参数传给构造器,执行;
  3. 如果构造器返回的是对象,则返回,否则返回第一步创建的对象

《JS高级程序设计》里可能说得更容易理解一些:

  1. 创建一个新对象
  2. 将构造函数的作用域赋给新对象(将 this 指向这个新对象)
  3. 执行构造函数里的代码(为新对象添加属性)
  4. 返回新对象

new 试图让函数对象在语法上跟类变得相似,但是,在客观上提供了两种方式

  1. 在构造器中添加属性
  2. 在构造器的 prototype 属性上添加属性
function c1(){
    this.p1 = 1;
    this.p2 = function(){
        console.log(this.p1);
    }
} 
var o1 = new c1;
o1.p2();
 
 
 
function c2(){
}
c2.prototype.p1 = 1;
c2.prototype.p2 = function(){
    console.log(this.p1);
}
 
var o2 = new c2;
o2.p2();

ES6 中的类

ES6 引入了 class 关键字,可以像基于类的语言一样写,虽然运行还是以原型运行:

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
  // Getter
  get area() {
    return this.calcArea();
  }
  // Method
  calcArea() {
    return this.height * this.width;
  }
}
  • constructor 方法,就是构造方法
  • this关键字则代表实例对象
  • 定义“类”的方法的时候,通过括号和大括号来创建方法,前面不需要加上function这个关键字,直接把函数定义-放进去了就可以了。方法之间不需要逗号分隔,加了会报错
  • 通过 get/set 关键字来创建 getter,数据型成员最好写在构造器里面。

类也有继承

class Animal {
constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(this.name + ' makes a noise.');
  }
}
 
class Dog extends Animal {
  constructor(name) {
    super(name); // call the super class constructor and pass in the name parameter
  }
 
  speak() {
    console.log(this.name + ' barks.');
  }
}
 
let d = new Dog('Mitzie');
d.speak(); // Mitzie barks.

相关文章

  • 重学前端(五)模拟类?

    配合另一篇博文「对 JS 创建对象的一些记录」一起食用效果会更好 JS 本身是面向对象的,所以不需要模拟,但是因为...

  • 前端→后台传参数,control类方法中如何接收

    前端/postman通过url模拟→后台传参数,control类方法中如何接收SpringBoot开发详解(五)-...

  • 《重学前端》读后感(开篇词)

    前段时间前端领域大火的课程《重学前端》,相信学习前端的同学都不陌生,尤雨溪、玉伯等顶级大佬都推荐跟着作者重学前端路...

  • HTML语义中使用的标签摘录

    前言 记录在《重学前端 - 04 | HTML语义:如何运用语义类标签来呈现Wiki网页?》使用到的标签,发现许多...

  • 重学前端(一)前言

    前言 重学前端是 winter 大神在极客学院开的一门课,虽然是重学“前端”,但是大神说的方法其实也适用于学习各个...

  • 快速理解 Web 语义化

    参考: winter 的重学前端 语义类标签是什么? 语义是我们说话表达的意思,多数的语义实际上都是由文字来承载的...

  • 重学前端

    一、类型和对象 1 类型 1.1 概述 javascript语言中,有6种基本类型和1种引用类型。引用类型还可以细...

  • 重学前端

    参考:重学前端 列一份前端知识架构图 用一定的词法和语法,表达一定语义,从而操作运行时。 运行时 = 数据结构 +...

  • 重学前端

    https://time.geekbang.org/column/article/77345 开篇词 | 从今天起...

  • 重学前端

    分享大佬的前端知识框架 有兴趣可以一起加入学习

网友评论

      本文标题:重学前端(五)模拟类?

      本文链接:https://www.haomeiwen.com/subject/qtmieqtx.html