Duxinyue's Technical Notes

website·Indexed 30 days ago

https://duxinyues.github.io/

A collection of technical notes and tutorials covering frontend development, including JavaScript (Promise, Proxy, Reflect, I/O streams, and File API), React and Redux (store, reducer, props, and state), CSS3 (variables, @media rules, and animations), Webpack, and Electron integration with Vue3, Vite, and TypeScript.

Tokens
50.6K
Snippets
206
Records
352
Agent score
74%

What's inside Duxinyue's Blog

  1. Overview of JavaScript Proxy and its basic usage

    A Proxy object allows you to create an interception layer in front of a target object. When external code accesses the object, it must pass through this layer, allowing you to filter or rewrite operations. The Proxy constructor takes two arguments: the target object to be proxied and a handler object containing 'traps' (interceptors). If a specific operation is not defined in the handler, the operation falls through to the target object.
    const proxy = new Proxy({}, {
        get: () => {
            console.log("get");
        },
        set: () => {
            console.log("set")
        }
    });
    
    proxy.count = 1; // Triggers 'set' trap
    ++proxy.count;   // Triggers 'get' trap
  2. Understand Node.js Stream types and Buffer behavior

    Node.js provides four primary types of streams for handling data from sources like files, memory, or networks:

    1. Readable: For reading data.
    2. Writable: For writing data.
    3. Duplex (Readable-Writable): For both reading and writing.
    4. Transform: A type of duplex stream that can modify the data stream during the read/write process.

    Streams utilize a Buffer as a temporary storage area. The size of this buffer is determined by the highWaterMark option in the stream's constructor. This parameter specifies the total number of bytes (or objects) the buffer can hold; once the buffer reaches this peak, the stream pauses reading from the data source.

  3. Understand Node.js Stream types and Buffer behavior

    In Node.js, I/O streams provide a mechanism to read data from or write data to devices (such as files, memory, or network sources). There are four primary types of streams:

    1. Readable: For reading data.
    2. Writable: For writing data.
    3. Duplex: Both readable and writable.
    4. Transform: A type of duplex stream that can modify the data as it is read and written.

    Streams utilize a Buffer to manage data. The size of this buffer is determined by the highWaterMark option in the stream's constructor. This parameter specifies the total number of bytes (or objects) the buffer can hold; once the buffer reaches this peak, the stream will pause reading from the data source.

  4. Understand the relationship between JSX and Fiber

    JSX is a syntactic sugar for React.createElement, allowing developers to describe node structures using HTML-like syntax. Fiber is a JavaScript object used to store node information and priority. During the initial render, JSX objects are used by createFiberFromElement to generate Fiber nodes. During updates, React compares the new JSX with the old JSX to generate a new Fiber tree.
  5. Reference the FiberNode structure

    The FiberNode is the core unit of the Fiber tree. It contains metadata about the component, its relationship to other nodes, and its current state/props.
    function FiberNode(
      tag: WorkTag,
      pendingProps: mixed, 
      key: null | string, 
      mode: TypeOfMode,
    ) {
      // Instance
      this.tag = tag; // Component type marker
      this.key = key; // React element key
      this.elementType = null; // Element type (first arg of createElement)
      this.type = null; // Resolved content of async components (function or class)
      this.stateNode = null; // Actual DOM node
    
      // Fiber Tree Structure
      this.return = null; // Pointer to parent node
      this.child = null; // Pointer to first child
      this.sibling = null; // Pointer to sibling node
      this.index = 0;
    
      this.ref = null; // ref attribute
    
      this.pendingProps = pendingProps; // New props from updates
      this.memoizedProps = null; // Props from previous render
      this.updateQueue = null; // Queue for component updates
      this.memoizedState = null; // State from previous render
      this.dependencies = null; 
    
      this.mode = mode; 
    
      // Effects
      this.flags = NoFlags;
      this.subtreeFlags = NoFlags;
      this.deletions = null;
    
      // Priority
      this.lanes = NoLanes;
      this.childLanes = NoLanes;
      // Pointer between current and workInProgress
      this.alternate = null;
    
      // Profiler timing
      if (enableProfilerTimer) {
        this.actualDuration = 0;
        this.actualStartTime = -1;
        this.selfBaseDuration = 0;
        this.treeBaseDuration = 0;
      }
    }
  6. Frontend performance optimization dimensions

    Frontend performance optimization should be approached from several key technical perspectives: network efficiency, browser rendering, build tool configuration, cross-platform technology implementation, and CDN (Content Delivery Network) optimization.
  7. Transpile ES6 to ES5 using Babel

    Babel is a JavaScript compiler that converts ES6 (and newer language features) into ES5. This allows developers to use the latest JavaScript syntax while ensuring compatibility with browsers that do not fully support ES6.
  8. Implement basic object interception using Proxy

    The Proxy object allows you to create a wrapper around a target object, intercepting fundamental operations. It takes two arguments: the target object to be wrapped and a handler object containing 'traps' (interceptors) for specific operations. If a trap is not defined in the handler, the operation falls through to the target object.
    const proxy = new Proxy({}, {
        get: () => {
            console.log("get");
        },
        set: () => {
            console.log("set")
        }
    });
    
    proxy.count = 1; // Triggers 'set' trap
    ++proxy.count;    // Triggers 'get' trap
  9. Compare Imperative vs Declarative UI patterns in JavaScript

    UI development generally follows two patterns: Imperative and Declarative.

    • Imperative UI: Focuses on the execution process and explicit steps to change the UI. It offers maximum performance because the developer specifies exactly what needs to change, but it is harder to maintain as the project grows. Examples include jQuery and native DOM manipulation.
    • Declarative UI: Focuses on the desired end result. The framework handles the process of updating the UI to match that state. It is significantly easier to maintain but introduces a performance overhead because the framework must calculate the difference between the current state and the new state (diffing).

    Examples of changing a div's text to 'hello world' on click:

    // Imperative: jQuery
    $("#app").text("hello world");
    
    // Imperative: Native JavaScript
    let app = document.querySelector('#app')
    app.addEventListener("click", function () {
        app.innerText = "hello world";
    })
    
    // Declarative: React
    import React from "react";
    function WordClassification() {
      const [text, setText] = React.useState('text');
      return <div onClick={() => { setText("hello world") }}>{text}</div>;
    }