Published on

5分钟速读系列-提供者模式/原型模式

Authors
  • avatar
    Name
    noodles
    每个人的花期不同,不必在乎别人比你提前拥有

这个系列是Improve how you architect webapps上文章的读书笔记。

提供者模式

提供者模式通过封装方法给予应用订阅不同数据源的能力。react中通过外层的Provider来提供全局的store,在组件内部通过useContext来获取相关的Context值。

        // 根组件通过Provider的value绑定全局store
        export const ThemeContext = React.createContext();
        const themes = {
            light: {
                background: "#fff",
                color: "#000"
            },
            dark: {
                background: "#171717",
                color: "#fff"
            }
        };
        export default function App() {
            const [theme, setTheme] = useState("dark");
            function toggleTheme() {
                setTheme(theme === "light" ? "dark" : "light");
            }
            const providerValue = {
                theme: themes[theme],
                toggleTheme
            };
            return (
                <div className={`App theme-${theme}`}>
                    <ThemeContext.Provider value={providerValue}>
                        <Toggle />
                    </ThemeContext.Provider>
                </div>
            );
        }
        // Toggle组件
        import React, { useContext } from "react";
        import { ThemeContext } from "./App";

        export default function Toggle() {
            const theme = useContext(ThemeContext);
            return (
                <label className="switch">
                    <input type="checkbox" onClick={theme.toggleTheme} />
                </label>
            );
        }

在React应用中通过全局的context可以解决组件属性的传递问题,便于组件的设计。但是全局Context的更新会导致消费对应Context组件的更新,造成需要不必要的渲染。这里就需要对全局Context进行更细粒度的拆分。

原型模式

JavaScript通过原型完成对象间属性的共享。通过原型能减少相同属性或者方法的创建,相同类型的实例可以共享实例原型上的属性和方法。对于原型模式需要理解几下的几点:

  • 实例对象的proto指向构造函数的prototype(实例与原型的关系).构造函数的prototype的constructor(构造函数与原型的关系).
class Dog {
  constructor(name) {
    this.name = name
  }
  bark() {
    return `Woof!`
  }
}
const dog1 = new Dog('Daisy')
dog1.__proto__ === Dog.prototype // true
Dog.prototype.constructor === Dog // true
  • 对象属性的获取是顺着对象proto沿着原型链查找,会一直查找到Object.prototype(Object.prototype.proto是null)

  • 理解new关键字中原型的处理方式,new操作符主要做了如下的操作:

    1. 以构造器的原型为属性创建新对象
    2. 将新对象作为this调用构造器
    3. 如果构造器返回的是对象则返回否则返回第一步创建的对象
function myNew(Con, ...args) {
  const obj = Object.create(Con.prototype)
  const ret = Con.call(obj, args)
  if (ret instanceof Object && ret !== null) {
    return ret
  }
  return obj
}