5

创建型-原型模式 - 风吹De麦浪

 1 year ago
source link: https://www.cnblogs.com/longbensong/p/17198551.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

创建型-原型模式

 使用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。原型模式是一种对象创建型模式---百科。

 通俗的说就是原型模式是一种创建型设计模式,指定某个对象(通过某种方式)得到一个新的对象,在内存中拥有新的地址,得到的对象与原对象是是相互独立的,即得到跟原对象一样的对象

 当我们需要两个一模一样的实例时,使用原型模式非常方便,如果不使用原型模式,按照构造函数的方式初始化对象,我们需要传两次一模一样的参数如:

const dog = new BydCard('byd', '汉', '30w', '2023款')const dog_copy = new BydCard('byd', '汉', '30w', '2023款')// 使用原型模式const dog_copy1 = Object.create(dog)

  通过目标对象得到一个全新的新对象,使新对象也具备跟目标对象一样的能力,这种一般思路有两种

  1. 指针引用:自身对象找不到,通过内部属性引用到目标对象上去找类似链表结构的next 指针

其中大多数后台语言如java 有相关克隆接口规范,javaScript 是通过第二种方式来实现的。

javaScript 中的原型模式

  在原型模式下,当我们想要创建一个对象时,会先找到一个对象作为原型,然后通过克隆原型的方式来创建出一个与原型一样(共享一套数据/方法)的对象。在 JavaScript 里,Object.create方法就是原型模式的天然实现——准确地说,只要我们还在借助Prototype来实现对象的创建和原型的继承,那么我们就是在应用原型模式。

  有的设计模式资料中会强调,原型模式就是拷贝出一个新对象,认为在 JavaScript 类里实现了深拷贝方法才算是应用了原型模式。事实上在 JavaScript 中,通过指针的方式也可以得到目标对象、属性、方法的共享。克隆(深度拷贝)是实现这个目的的方法,但不是唯一的方法,也不是javaScript 的目的。

通过指针来引用,然后动态执行的时候绑定上下文 this,这样就不会造成实例之间的错乱,我觉得这也是this 被设计成动态绑定的原因之一。

原型模式-编程范式

  原型模式不仅是一种设计模式,它还是一种编程范式(programming paradigm),是 JavaScript 面向对象系统实现的根基,原型编程范式的体现就是基于原型链的继承。即便现在es6+ 推出了class 关键字,支持了类的写法。引入的 JavaScript 类本质上还是基于原型的继承的语法糖(class 只是一个语法糖)。类语法不会为 JavaScript 引入新的面向对象的继承模型。 当我们尝试用 class 去定义一个 Dog 类时:

class Dog { constructor(name ,age) { this.name = name this.age = age } eat() { console.log('肉骨头真好吃') }}

其实完全等价于写了这么一个构造函数:

function Dog(name, age) { this.name = name this.age = age}Dog.prototype.eat = function() { console.log('肉骨头真好吃')}

原型链核心点

  每个构造函数都拥有一个prototype属性,它指向构造函数的原型对象,这个原型对象中有一个 constructor 属性指回构造函数;每个实例都有一个内部属性__proto__属性,当我们使用构造函数去创建实例时,实例的__proto__属性就会指向构造函数的原型对象。

// 输出"肉骨头真好吃"dog.eat()// 输出"[object Object]"dog.toString()

明明没有在 dog 实例里手动定义 eat 方法和 toString 方法,它们还是被成功地调用了。这是因为当我试图访问一个 JavaScript 实例的属性、方法时,它首先搜索这个实例本身;当发现实例没有定义对应的属性、方法时,它会转而去搜索实例的原型对象;如果原型对象中也搜索不到,它就去搜索原型对象的原型对象,这个搜索的链表就叫做原型链。

825196-20230309145959973-1875258561.png

Object 是所有的基类,其中Object.prototype指向null,这样原型链就有终点了,而不是无脑的一直下去。

原型链其他关键点:

  1. 所有函数(普通函数,构造函数,内置的函数)都是内置函数(类)Function 的实例,所以存在函数.__proto__ === Function.prototype 所有函数都可以直接调用Function原型上的方法(call / apply /bind)
  2. Function 确实很厉害,他不仅是函数的类,还是自己的类。函数是Function 的实例,Function 也是Function 的实例 Object.__proto__ === Function.prototypeFunction.__proto__===Function.prototype
  3. 对象的原型链最终指向Object.prototype, object.prototype._proto_ 指向null

如下代码验证了这些结论:

function sayHi () { // console.log('hello joel')} // 所有函数都是Function 的实例即函数也是对象,// 所以存在函数.__proto__ === Function.prototypeconsole.log(sayHi.__proto__ === Function.prototype) // trueconsole.log(Object.__proto__ === Function.prototype) // trueconsole.log(String.__proto__ === Function.prototype) // trueconsole.log(Array.__proto__ === Function.prototype) // trueconsole.log(Number.__proto__ === Function.prototype) // trueconsole.log(Symbol.__proto__ === Function.prototype) // true // Function.prototype 内部属性又指向Object的原型对象console.log(Function.prototype.__proto__ === Object.prototype) // true// Function 也是Function 的实例console.log(Function.__proto__ === Function.prototype)// 对象最终指向object的原型console.log(new sayHi().__proto__ instanceof Object) // trueconsole.log(new sayHi().__proto__ === sayHi.prototype) // trueconsole.log(Array.prototype.__proto__ === Object.prototype) // trueconsole.log(Object.__proto__.__proto__ === Object.prototype) // true // 内置的array,string,number,object 等都是构造函数,同时也是对象console.log(typeof Array) // functionconsole.log(typeof Object) // function // 通过原型链找到object.prototype 上的方法sayHi.valueOf()
  1. 原型是 JavaScript 面向对象系统实现的根基,在这里更像是一种编程范式
  2. 在JavaScript 中原型模式无处不在,只要使用原型的模型创建对象就是在使用原型模式
Object.__proto__ === Function.prototypeFunction.__proto__=== Function.prototypeFunction.prototype.__proto__ === Object.prototypeObject.prototype.__prto__ === null

如果您觉得阅读本文对您有帮助,请点一下推荐按钮,您的推荐将是我最大的写作动力,欢迎各位转载!

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK