2022-09-29JavaScript00

ES6

var、let 及 const 区别?

  • 全局申明的 var 变量会挂载在 window 上,而 let 和 const 不会
  • var 声明变量存在变量提升,let 和 const 不会
  • let、const 的作用范围是块级作用域,而 var 的作用范围是函数作用域
  • 同一作用域下 let 和 const 不能声明同名变量,而 var 可以
  • 同一作用域下在 let 和 const 声明前使用会存在暂时性死区
  • const
    • 一旦声明必须赋值,不能使用 null 占位
    • 声明后不能再修改
    • 如果声明的是复合类型数据,可以修改其属性

Proxy

Proxy 是 ES6 中新增的功能,它可以用来自定义对象中的操作。 Vue3.0 中将会通过 Proxy 来替换原本的 Object.defineProperty 来实现数据响应式。

let p = new Proxy(target, handler);

target 代表需要添加代理的对象,handler 用来自定义对象中的操作,比如可以用来自定义 set 或者 get 函数。

let onWatch = (obj, setBind, getLogger) => {
  let handler = {
    set(target, property, value, receiver) {
      setBind(value, property);
      return Reflect.set(target, property, value);
    },
    get(target, property, receiver) {
      getLogger(target, property);
      return Reflect.get(target, property, receiver);
    },
  };
  return new Proxy(obj, handler);
};

let obj = { a: 1 };
let p = onWatch(
  obj,
  (v, property) => {
    console.log(`监听到属性${property}改变为${v}`);
  },
  (target, property) => {
    console.log(`'${property}' = ${target[property]}`);
  }
);
p.a = 2; // 控制台输出:监听到属性a改变
p.a; // 'a' = 2
2022-09-29React00

自定义 hooks

因为可以自定义 Hooks, 我们可以非常方便的复用状态逻辑。

// 定时器DEMO
function useCount(defaultCount) {
  const [count, setCount] = useState(defaultCount);
  const timer = useRef();

  useEffect(() => {
    timer.current = setInterval(() => {
      setCount((count) => count + 1);
    }, 1000);
  }, []);

  useEffect(() => {
    if (count >= 10) {
      clearInterval(timer.current);
    }
  });
  return [count];
}

function App() {
  const [count] = useCount(0);
  return (
    <>
      <h1>count: {count}</h1>
    </>
  );
}
2022-09-29Webpack00

webpack 配置文件

webpack.config.js

webpack.config.js 是 webpack 的默认打包配置文件。也可以npx webpack --config 配置文件名手动设置

/**
 * Wepack配置接口
 */
const path = require("path");

module.exports = {
  // 打包模式
  mode: "production",
  // 入口
  entry: "./index.js",
  // 出口
  output: {
    filename: "bundle.js",
    // path 后必须是一个绝对位置
    path: path.resolve(__dirname, "bundle"),
  },
};

其中entry: "./index.js"是一个简写,

entry: {
    main: "./index.js"
}
2022-09-29Webpack00

缓存

webpack 中的 hash、chunkhash、contenthash 区别

hash 一般是结合 CDN 缓存来使用,通过 webpack 构建之后,生成对应文件名自动带上对应的 MD5 值。如果文件内容改变的话,那么对应文件哈希值也会改变,对应的 HTML 引用的 URL 地址也会改变,触发 CDN 服务器从源服务器上拉取对应数据,进而更新本地缓存。但是在实际使用的时候,这几种 hash 计算还是有一定区别。

  1. hash    hash 是跟整个项目的构建相关,只要项目里有文件更改,整个项目构建的 hash 值都会更改,并且全部文件都共用相同的 hash 值

  2. chunkhash

采用 hash 计算的话,每一次构建后生成的哈希值都不一样,即使文件内容压根没有改变。这样子是没办法实现缓存效果,我们需要换另一种哈希值计算方式,即 chunkhash。    chunkhash 和 hash 不一样,它根据不同的入口文件(Entry)进行依赖文件解析、构建对应的 chunk,生成对应的哈希值。我们在生产环境里把一些公共库和程序入口文件区分开,单独打包构建,接着我们采用 chunkhash 的方式生成哈希值,那么只要我们不改动公共库的代码,就可以保证其哈希值不会受影响。

  1. contenthash

在使用 chunkhash 的例子中,如果 index.css 被 index.js 引用了,那么就会共用相同的 chunkhash 值。但是这样子有个问题,如果 index.js 更改了代码,css 文件就算内容没有任何改变,由于是该模块发生了改变,导致 css 文件会重复构建。

这个时候,我们可以使用 extra-text-webpack-plugin 里的 contenthash 值,保证即使 css 文件所处的模块里就算其他文件内容改变,只要 css 文件内容不变,那么不会重复构建。

2022-09-29Webpack00

sourcemap

Source map 就是一个信息文件,里面储存着位置信息。也就是说,转换后的代码的每一个位置,所对应的转换前的位置。

源文件

function sayHello(name) {
  if (name.length > 2) {
    name = name.substr(0, 1) + "...";
  }
  console.log("hello,", name);
}

压缩后

function sayHello(name) {
  if (name.length > 2) {
    name = name.substr(0, 1) + "...";
  }
  console.log("hello,", name);
}
sayHello("世界");
sayHello("第三世界的人们");

map 文件

{"version":3,"sources":["log.js","main.js"],"names":["sayHello","name","length","substr","console","log"],"mappings":"AAAA,SAASA,SAASC,MACd,GAAIA,KAAKC,OAAS,EAAG,CACjBD,KAAOA,KAAKE,OAAO,EAAG,GAAK,MAE/BC,QAAQC,IAAI,SAAUJ,MCJ1BD,SAAS,MACTA,SAAS"}