JavaScript原形,但程序设计模式中的原型模式你能使用

lxf2023-03-15 17:51:01

背景资料

这也是程序设计模式系列第八节,学习培训是指patterns.dev里程序设计模式中混合模式具体内容,因为是材料是英语版,所以我的学习心得就含有汉语翻译的特性,但是并不是汉语翻译,纪录的是自己学习的过程与理解

第一节:分布式系统所造成的数据分析艰难?看着我单例设计模式一招制敌

第二节:JS和热巴一样有专门替身演员?没听说过的赶紧来补补习...

第三节:仍在逐层传送props?来学习非常实用的经销商方式

第四节:都懂JavaScript原形,但程序设计模式中的原型模式你能使用吗?

第五节:React Hooks时期,如何完成主视图与逻辑性分离出来呢?

第六节:现在是时候取出高档的技术了————观察者模式

第七节:前面性能调优实战篇——动态加载控制模块基本补遗

写在前面

前边大家学习原型模式时,学习培训了一些关于原形基础知识,我们都知道根据原形是能够给对象添加属性和方法。并且通过Object.assign方式或是proto特性添加属性,其实就是今天给大家说的混合模式

简约释意

不能使用传承的情形下给Object目标或是class类加上函数公式。

基本完成方法就是使用Object.assign方式给总体目标类原型(prototype)上添加属性, 随后创好的对象都能够浏览添加的函数公式。

class Dog {
  constructor(name) {
    this.name = name;
  }
}

const dogFunctionality = {
  bark: () => console.log("Woof!"),
  wagTail: () => console.log("Wagging my tail!"),
  play: () => console.log("Playing!")
};

Object.assign(Dog.prototype, dogFunctionality);

根据给Dog这一类原型加上方式,如今我们能直接启用新增加的方式了:

const pet1 = new Dog("Daisy");

pet1.name; // Daisy
pet1.bark(); // Woof!
pet1.play(); // Playing!

被混合在一起Object中间可以用传承

混合模式容许给Class和Object不能使用传承加上属性和方法,与此同时被混和的Object之间有能够应用传承的。

看看下面的事例:

const animalFunctionality = {
  walk: () => console.log("Walking!"),
  sleep: () => console.log("Sleeping!")
};

const dogFunctionality = {
  bark: () => console.log("Woof!"),
  wagTail: () => console.log("Wagging my tail!"),
  play: () => console.log("Playing!"),
  walk() {
    super.walk();
  },
  sleep() {
    super.sleep();
  }
};

Object.assign(dogFunctionality, animalFunctionality);
Object.assign(Dog.prototype, dogFunctionality);

在后面的例子中,我们先应用Object.assign给dogFunctionality加了小动物animalFunctionality的函数公式,接着又把dogFunctionality中的函数公式加上给Dog这一类原形

这个案例能够换个原型的书写Proto来达到,一个意思:

class Dog {
  constructor(name) {
    this.name = name;
  }
}


const animalFunctionality = {
  fly: ()=>console.log("fly"),
  walk: () => console.log("Walking!"),
  sleep: () => console.log("Sleeping!")
};


const dogFunctionality = {
  __proto__: animalFunctionality,
  bark: () => console.log("Woof!"),
  wagTail: () => console.log("Wagging my tail!"),
  play: () => console.log("Playing!"),
  walk() {
    super.walk();
  },
  sleep() {
    super.sleep();
  }
};

Object.assign(Dog.prototype, dogFunctionality);

const pet1 = new Dog("Daisy");

console.log(pet1.name); // Daisy
pet1.bark(); // Woof!
pet1.play(); // Playing!
pet1.walk(); // Walking!
pet1.sleep(); // Sleeping!

// 调节
pet1.fly(); // Error, pet1.fly is not a function

console.log(pet1.__proto__); //{bark...wagTail...play...walk...sleep}
console.log(Dog.prototype); //{bark...wagTail...play...walk...sleep}
console.log(dogFunctionality.__proto__); //{fly...walk...sleep}
console.log(animalFunctionality.__proto__); //{}

线上实例

需注意,dogFunctionality 原型的方式fly,Dog类中没法启用;

给Dog加上原型,并没有把所加上原型的原形中的方式给加上上;

Dog浏览原形用prototype, Dog的实例对象或其它随意目标经过**_proto_**浏览原形;

只支持函数公式,不兼容别的特性;

经典案例

电脑浏览器window目标

在实际的运用中一个较为明显混合模式是电脑浏览器页面中的window目标。window对象许多特性完成自WindowOrWorkerGlobalScopeWindowEventHandler的组合,最后我们才能进行例如setTimeoutsetInterval,indexedDB, 和isSecureContext这种特性。

由于混合模式下,只有完成给Object对象添加函数公式特性,而无法直接启用例如WindowOrWorkerGlobalScope 这种目标。

window.indexedDB.open("toDoList");


window.addEventListener("beforeunload", event => {
  event.preventDefault();
  event.returnValue = "";
});


window.onbeforeunload = function() {
  console.log("Unloading!");
};
// 能够启用混匀的特性
console.log(
  "From WindowEventHandlers mixin: onbeforeunload",
  window.onbeforeunload
);


console.log(
  "From WindowOrWorkerGlobalScope mixin: isSecureContext",
  window.isSecureContext
);

// 能够启用被混合在一起目标
console.log(
  "WindowEventHandlers itself is undefined",
  window.WindowEventHandlers
);


console.log(
  "WindowOrWorkerGlobalScope itself is undefined",
  window.WindowOrWorkerGlobalScope
);

ES6以前的React

在React引进ES6以前,频繁使用混合模式给React部件加上函数公式。

React团队并不建议应用混合模式,由于这时候给部件产生不必要复杂性,而且无法日常维护重复使用;反而是建议使用高阶函数,其实现在大多数被hooks方法替代了。

汇总

混合模式容许大家在不能使用传承的情形下,用给目标原形引入函数公式的形式,进而真正实现地对对象添加函数公式。可是改动目标原形通常并并不是好的方式,因为他们可能会致使原形环境污染和一定程度的函数公式追溯错乱

打开AdminJS成长之路!这个是我参加「AdminJS日新的目标 · 2 月更文考验」第 1 天,查看更多活动规则