zoukankan      html  css  js  c++  java
  • 红宝书4-第八章对象、类与面向对象编程(3)


    创建对象

    概述

    ECMAScript 6 开始正式支持类和继承。ES6 的类旨在完全涵盖之前规范设计的基于原型的继承模 式。不过,无论从哪方面看,ES6的类都仅仅是封装了 ES5.1构造函数加原型继承的语法糖而已。

    工厂模式

    工厂模式是一种众所周知的设计模式,广泛应用于软件工程领域,用于抽象创建特定对象的过程。 就是创建一个类似工厂的函数,来帮助我们完成一些需要重复进行的操作,就比如我们对象的创建。
    在这里插入图片描述
    这种工厂模式虽 然可以解决创建多个类似对象的问题,但没有解决对象标识问题(即新创建的对象是什么类型)

    构造函数模式

    在这里插入图片描述
    要注意函数名 Person 的首字母大写了。

    要创建 Person 的实例,应使用 new 操作符。以这种方式调用构造函数会执行如下操作
    在这里插入图片描述

    用 instanceof 操作符 确定对象类型

    console.log(person1 instanceof Object);  // true 
    console.log(person1 instanceof Person);  // true 
    console.log(person2 instanceof Object);  // true 
    console.log(person2 instanceof Person);  // true
    

    赋值给变量的函数表达式也可以表示构造函数

    在这里插入图片描述
    在实例化时,如果不想传参数,那么构造函数后面的括号可加可不加。只要有 new 操作符,就可以 调用相应的构造函数

    构造函数也是函数

    如果把构造函数用普通函数调用的方式进行调用,咱们函数中的this 就会指向全局的gloal对象(即window对象)。
    我可以用 call apply bind来改变一个函数中的 this 指向。三者的区别就是前两哥函数会进行调用,最后一个会返回一个新函数,函数不会进行调用。其他的区别就不在这里赘述了。call 的调用方式如下:

    // 作为构造函数  
    let person = new Person("Nicholas", 29, "Software Engineer"); 
    person.sayName();    // "Nicholas" 
     
    // 作为函数调用 
    Person("Greg", 27, "Doctor");   // 添加到 window 对象 
    window.sayName();    // "Greg" 
     
    // 在另一个对象的作用域中调用 
    let o = new Object(); 
    Person.call(o, "Kristen", 25, "Nurse"); 
    o.sayName();   // "Kristen"
    

    构造函数的问题

    构造函数虽然有用,但也不是没有问题。构造函数的主要问题在于,其定义的方法会在每个实例上 都创建一遍。因此对前面的例子而言,person1 和 person2 都有名为 sayName()的方法,但这两个方 法不是同一个 Function 实例

    这个新 问题可以通过原型模式来解决。

    原型模式

    使用原型对象的好处 是,在它上面定义的属性和方法可以被对象实例共享

    function Person() {} 
     
    Person.prototype.name = "Nicholas"; 
    Person.prototype.age = 29;
     Person.prototype.job = "Software Engineer"; 
     Person.prototype.sayName = function() {   console.log(this.name);  }; 
     
    let person1 = new Person(); person1.sayName(); // "Nicholas" 
     
    let person2 = new Person(); person2.sayName(); // "Nicholas" 
     
    console.log(person1.sayName == person2.sayName); // true 
    

    与构造函数模 式不同,使用这种原型模式定义的属性和方法是由所有实例共享的。因此 person1 和 person2 访问的 都是相同的属性和相同的 sayName()函数。

    理解原型

    关键在于理解这一点:实例与构造函数原型之间有直接的联系,但实例与构造函数之 间没有。

    在这里插入图片描述
    展示了 Person 构造函数、Person 的原型对象和 Person 现有两个实例之间的关系。注意, Person.prototype 指向原型对象,而 Person.prototype.contructor 指回 Person 构造函数。原 型对象包含 constructor 属性和其他后来添加的属性。Person 的两个实例 person1 和 person2 都只 有一个内部属性指回 Person.prototype,而且两者都与构造函数没有直接联系。另外要注意,虽然这两 个实例都没有属性和方法,但 person1.sayName()可以正常调用。这是由于对象属性查找机制的原因。

    isPrototypeOf()确定两个对 象之间的这种关系

    本质上,isPrototypeOf()会在传入参数的[[Prototype]]指向调用它的对象时 返回 true,如下所示:

    console.log(Person.prototype.isPrototypeOf(person1));  // true
    console.log(Person.prototype.isPrototypeOf(person2));  // true 
    

    Object.getPrototypeOf()返回参数的内部特性 [[Prototype]]的值。

    console.log(Object.getPrototypeOf(person1) == Person.prototype);  // true
    console.log(Object.getPrototypeOf(person1).name);                 // "Nicholas"
    

    setPrototypeOf()方法可以向实例的私有特性[[Prototype]]写入一 个新值

    let biped = {    numLegs: 2 }; let person = {   name: 'Matt' }; 
     
    Object.setPrototypeOf(person, biped); 
     
    console.log(person.name);                              // Matt 
    console.log(person.numLegs);                           // 2
    console.log(Object.getPrototypeOf(person) === biped);  // true 
    

    在这里插入图片描述
    为避免使用 Object.setPrototypeOf()可能造成的性能下降,可以通过 Object.create()创 建一个新对象,同时为其指定原型

    在这里插入图片描述


        感谢您花时间阅读此篇文章,如果您觉得看了这篇文章之后心情还比较高兴,可以打赏一下,请博主喝上一杯咖啡,让博主继续码字……
        本文版权归作者和博客园共有,来源网址:https://blog.csdn.net/weixin_46498102 欢迎各位转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接
  • 相关阅读:
    python实现布隆过滤器及原理解析
    gin框架源码解析
    阿里云docker操作问题记录
    Qt编写数据可视化大屏界面电子看板系统
    CSS3-3D制作案例分析实战
    前端可视化项目流程,涉及three.js(webGL),3DMax技术,持续更新
    前端可视化项目流程,涉及three.js(webGL),3DMax技术,持续更新
    jquery拖拽排序,针对后台列表table进行拖拽排序(Echart不刷新页面,多语言切换下的地图数据重新加载,api请求数据加载
    Java 设置Excel条件格式(高亮条件值、应用单元格值/公式/数据条等类型)C# 创建Excel气泡图
    Java 如何在PPT中设置形状组合、取消组合、编辑组合形状
  • 原文地址:https://www.cnblogs.com/jackson1/p/13799755.html
Copyright © 2011-2022 走看看