深入探究Prototype与原型链

Prototype_proto_的区别

  • Prototype属性(原型对象)。是函数(Function)独有的属性,非函数类对象没有这个属性。作用是,作为一个“公共仓库”,用来放置希望所有实例共享的属性和方法。
  • _proto_属性(隐式原型指针)。JavaScript 中的每一个对象(包含函数、数组、实例等)都有。作用是,指向创建该对象的构造函数的 prototype。它就是对象用来“向上查找”的连接线。

一个函数对象拆解后的实际样子

要彻底搞懂一个函数对象在内存和浏览器控制台里的完整拆解结构,我们可以将它划分为 4 大核心板块

在 Chrome 控制台中运行 console.dir(Foo) 并展开后,你能看到它的全部内部组成:

function Foo(name) {
  this.name = name;
}
Foo.prototype.sayHello = function() {};
Foo.myStaticMethod = function() {}; // 静态方法

console.dir(Foo);

函数对象的 4 大结构板块

板块 1:函数自身的常规属性(静态属性与方法)

这是挂载在函数本身上的属性。当你把函数当成普通对象使用时(例如 Foo.myStaticMethod = ...),这些属性直接存在于函数自身。

  • name:函数名(如 "Foo")。
  • length:形参个数(如 1)。
  • 自定义静态属性/方法:例如 myStaticMethodArray.isArrayObject.keys 等。

板块 2:prototype(显式原型板块 —— “供实例调用的共享仓库”)

这个板块专门负责给由 new Foo() 创建出来的实例对象提供共享的方法和属性。

  • 主要内容:
    1. 自定义共享方法/属性:例如 sayHello,所有实例共享此方法。
    2. constructor(构造器指针):默认存在,反向指回函数 Foo 本身(Foo.prototype.constructor === Foo)。
    3. [[Prototype]](原型的原型)Foo.prototype 本身也是一个普通对象,所以它也有自己的 [[Prototype]],指向 Object.prototype

板块 3:[[Prototype]](隐式原型板块 —— “函数自身的继承通道”)

这是函数自身作为对象所拥有的原型,指向 Function.prototype。因为函数本身也是由 JavaScript 的内置构造函数 Function 创建的。

  • 主要内容:
    1. 内置函数方法call()apply()bind()toString() 等。你能在任何函数上直接调用 Foo.call(),就是从这个板块里继承来的。
    2. constructor:指向 Function 构造函数。
    3. [[Prototype]]:指向 Object.prototype(原型链继续向上查找)。

板块 4:内部槽 / 隐式作用域(引擎私有板块)

控制台中以 [[...]] 双方括号包裹的内容,属于 JavaScript 引擎内部维护的私有属性。

  • [[Scopes]]:函数的作用域链(包含了函数定义时的闭包 Closure、全局作用域 Global 等)。
  • [[FunctionLocation]]:源代码中该函数定义的文件和行号位置。

控制台展开结构对照表

在 Chrome / Edge 控制台里展开 console.dir(Foo),对应结构如下:

板块名称在控制台中的显示内容是什么谁会用到它
自身属性name, length, myStaticMethod函数名、形参个数、静态属性/方法函数自身(如 Foo.myStaticMethod()
prototype 板块prototypesayHello, constructor: ƒ Foo(), [[Prototype]]: Objectnew Foo() 生成的实例
[[Prototype]] 板块[[Prototype]]: ƒ ()call(), apply(), bind(), constructor: ƒ Function()函数 Foo 自身
作用域与元数据[[Scopes]], [[FunctionLocation]]闭包变量(Closure)、环境上下文、代码源码位置JS 执行引擎

代码验证(一秒分清两个 Prototype)

JavaScript

// 1. 查看 Foo 给【实例】准备的共享仓库 (板块 2)
console.log(Foo.prototype.sayHello); // ƒ () {}

// 2. 查看 Foo 【自己】调用的函数能力 (板块 3)
console.log(Foo.call); // ƒ call() { [native code] }

// 验证:Foo 的 [[Prototype]] 就是 Function.prototype
console.log(Object.getPrototypeOf(Foo) === Function.prototype); // true

彻底理解JavaScript中的对象

JS对象迷惑性:理解本质

对于C++、Java、C#面向对象的语言而言,对象这个词都是很明确的:“对象”必须以“类(Class)”为模板实例化而来。

而JS中的对象概念,则宽泛得多。例如,以下代码中的staff 、p都是对象,甚至函数Person也是对象:

//普通对象
const staff = {
    name: "Tom",
    age: 18
};

//Promise对象
const p = new Promise(...);

//函数也是一个对象
function Person(name) {
  this.name = name;
}

这不禁让人困惑,JavaScript的对象到底指的是什么?

因为中文把 Object 翻译成“对象”,听起来特别抽象,实际上:

JS 里的“对象”并不是指某一种长相,而是指一种“可以被当成一个整体来管理,并且可以通过属性名找到内部东西”的值。

“对象”本质上只是一个包含键值对(Key-Value)的动态哈希表。

很粗浅的理解,对象就是一个可以装很多“属性”的东西。

认识了这个本质,我们很快就能理解了,staff,p,Person 长相完全不同,但它们在 JavaScript 的底层分类上都属于 Object。以下都是JS中的对象,只是创建它们的“模板”不同而已:

JavaScript Object

├── 普通对象
├── Promise对象
├── Array对象
├── Date对象
├── RegExp对象
├── Map对象
└── …

创建对象有很多种方式

例如,普通对象:

 const a = {};

其它类型对象:

 //Promise 对象
 const b = new Promise(...);
 //Array 对象。
 const c = [];
 //Date 对象
 const d = new Date();
 //Map 对象
 const e = new Map();
 //RegExp 对象
 const f = /abc/;
  //甚至得到的是函数对象
 const g = function() {};

不要再把对象单一理解成:

 { name: “Tom”, age: 18 }

而应该理解成:

对象 = 一个可以拥有属性和方法、可以被独立操作的实体。

于是:

                  Object
                    │
        ┌───────────┼────────────┐
        ↓           ↓           ↓
      普通对象     Array       Promise
        │           │           │
    name/age     push/length   then/catch

它们虽然功能完全不同,但都属于“对象”这个大类别。

HTTP方法的深度探源与RESTful API的设计思想

HTTP认知溯源

HTTP方法本质上就是一个普通的 ASCII 编码字符串,我们可以自定义HTTP方法。从这一点看每个http方法没有什么区别。但是,在应用层,考虑到缓存与网络效能、容错与重试机制、安全隔离与攻击防御等,浏览器、路由器、防火墙、CDN节点、NGINX等应用对各方法做了区别对待。

HTTP方法是在安全和幂等的理念下设计的,语义化的命名有助于互联网生态的协作,在缓存、爬虫、搜索、CDN分发、前后端数据交互等方面能更低成本协作。而REST则是一种设计API的理念,即使用 URI 来标识资源,使用标准的 HTTP 方法 来表示操作。RESTful则是符合这种理念的API。

即使写程序很多年的老鸟,能真正说清楚道明白HTTP方法的也不多,多数都只会使用而不知道所以然。每个人都知道使用GET、POST方法,使用也很熟练,但是底层设计思想并不一定了解。这里,来认真梳理一下HTTP方法背后设计的逻辑。

一. HTTP方法常见10种

HTTP 标准里常见的10 个:

方法主要作用
GET获取资源
POST提交数据 / 创建资源
PUT完整替换资源
PATCH部分修改资源
DELETE删除资源
HEAD获取响应头,不返回正文
OPTIONS查询服务器支持哪些方法/能力
CONNECT建立隧道
TRACE请求回显,用于诊断
QUERY用于查询搜索(2026年RFC10008新增)

(实际上HTTP方法数量多达几十种,这里只是列举常见的方法,详见文末)

二.HTTP方法两个核心设计理念:安全(Safe) 与 幂等(Idempotent)


注意:以上的标准是2014年颁布的RFC 7231,QUETY标准出自2026颁布的RFC 10008

FastAPI + HarfBuzz + Redis实现动态字体子集化实战

字形编译引擎(Text Shaping Engine)当今的绝对王者HarfBuzz,拥有极强性能,Android、Chromium、Firefox等主流应用底层都在用它。HarfBuzz有一个hb-subset 子集化模块,是专业的字体子集化引擎:

当你给它一段文本(比如 "动态字体子集化")和原字体时,HarfBuzz 会:
自动分析这几个汉字对应的 Glyph ID。
保留这几个字所需的矢量描边数据。
剔除其余上万个未用到的字形数据
重构并修复 .ttf 文件的 OpenType 内部索引表,确保输出的小字体符合国际标准,能在浏览器中被完美加载。

直观了解:HarfBuzz是做什么的

官方是这样介绍的:


harfbuzz-world.cc is a single-file build of HarfBuzz that drops into your own C or C++ project without any build-system glue, plus a live playground for it right here in your browser:

harfbuzz-world.cc 提供了一个单文件版的 HarfBuzz(HarfBuzz 整个库整合成一个可以直接编译的 .cc 文件。),可以直接放进你自己的 C/C++ 项目中,无需额外处理构建系统;同时,它还在浏览器中提供了一个可以实时操作的 HarfBuzz 实验场。


shape — the shaped glyph stream as a table, alongside an SVG preview.(字形整形 / 字形塑形)
subset — produce a font subset for the current text and download it.(子集化)
raster — pixel-perfect BGRA rendering at any size, blitted to a canvas.(光栅化/位图化)
vector — the same shaped text rendered to SVG and downloadable PDF.
gpu — slug-based GPU rendering via WebGL2.(GPU 渲染)

官网地址:https://harfbuzz-world.cc/



OpenType(包括排版规则、连字、变形、字形定位表等)也是一套极其复杂的标准规范,而 HarfBuzz 就是这套标准在全世界最权威、最完美的执行引擎(“编译器/解析引擎”)。 很多人以为:计算机显示文本 = 查字典(给一个字符编码,找到对应的字体形状画出来)。 如果全世界只有英文字母(A-Z),这确实很简单。但在现实世界中,文字的显示极其复杂:

—— 复杂连字(Ligatures)与形态变化:阿拉伯文同一个字母,在词首、词中、词尾、单独存在时,形状完全不同,而且必须连笔。印地文/泰文: 辅音和元音组合时,元音符号可能会跑到辅音的上方、下方甚至左边。英文在优雅的排版中,f 和 i 连着写时,f 的横线和 i 的点会融合成一个整体(fi 连字)。

—— 字形(Glyph)与字符(Character)不是一回事。字符(Unicode):是逻辑上的编码(如 U+0061 代表 a)。字形(Glyph):是字体文件(.ttf)中实际绘制出来的矢量图形。一个字符可能对应多个字形,多个字符也可能合成一个字形。

HarfBuzz 的核心工作,这串文本在当前字体下,应该使用字体库里的哪几个字形(Glyph ID)?每个字形应该放在什么坐标位置?字形之间的间距(Kerning)是多少?

说得更直白一些,HarfBuzz就是把字体规则给完美呈现出来,就像浏览器,要把庞大复杂的HTML/CSS/Javascript这些规则给视觉实现,HarfBuzz就是字体界的浏览器。

由于项目需要,我们需要做动态字体子集化,HarfBuzz是不二之选。我们采用的是Python FastAPI + HarfBuzz + Redis+Nginx+Vue3+pdf-lib前后端技术栈来实现。以下的记录是其中一些操作要点。

繁荣的根基:制度与人文的力量——读《Leaders》

繁荣的背后是自由的制度和对知识专业的尊重

中华民国在台湾的经济奇迹,不是偶然,尼克森原版回忆录,记述了两种制度在海峡两岸造成的巨大差距背后原因。经济繁荣背后是永恒的自由、对知识和市场的尊重,无它。

读尼克松(Richard Nixon)的原版回忆录《Leaders》,看到很多历史的细节,完全打破原来的认知。其中最震撼的一点就是关于台湾经济起飞原因的描述:

Chiang was an example of that rarest of political animals: the conservative revolutionary. The American Revolution succeeded in founding an orderly and free society because its leaders were essentially conservatives. They fought for freedoms that they had once possessed, but which had been taken away. The French Revolution foundered as it did partly because its leaders sought to achieve a purely intellectual and abstract vision that had no foundations in their national history.

蒋中正是一个极少见的、天生的政治领袖,他是一个保守主义革命志士。美国革命之所以能够成功建立一个有序且自由的社会,是因为其领袖本质上都是保守主义者,他们夺回了曾经有过但被剥夺了的自由。而法国革命之所以失败,部分原因在于其领导者试图实现一种纯粹理性的、抽象的幻想,而这种革命幻想在法国历史中毫无根基。

Chiang’s intenions resembled those of the Americans more than those of the French. He wanted to revivify Chinese tradition. He rejected its corruption by the old order. He fought against pervasive opium addiction and the still-common practice of foot binding. But he was not a democrat, even though he did introduce constitutional government. The problem, as he saw it,was not too little freedom but too much. China needed discipline, for as Sun Yat-sen had stated, “We have become a heap of sand.” The discipline Chiang sought, however, would release the creative and productive abilities of the Chinese people.

蒋中正的革命理念走的是美国路线,而非法国。他希望能复兴中国传统文化。他摒弃旧社会的腐败,取缔当时普遍存在的吸食鸦片和缠足陋习。他带领中国进入宪政,尽管他不是传统意义上的民主人士。在他看来,问题的核心不在于自由太少,而在于自由过度。中国需要秩序,正如孙中山所言:“中国人是一盘散沙” ,蒋中正所寻求的纪律,是为了释放中国人的创造力与生产力。

When implemented on Taiwan, his ideas produced an economic miracle.Though he received American economic aid through 1965, the amounts were so small that they cannot account for the country’s explosive economic growth. Economic statistics can never capture the tragedy that the Communist victory was for the Chinese people, but they do make some important points.The Communists collectivized agricultural production, and today the mainland produces less rice per capita than it did before the revolution. Chiang paid the landlords for their land and distributed it to the peasantry. The former landlords invested much of their money in industry while the government encouraged foreign investment. Today, Taiwan has a per capita income five times as great as that of the mainland. And the eighteen million Chinese on Formosa export about fifty percent more than the one billion on the mainland.

蒋中正的理念在台湾实施后,创造了经济奇迹。在1965年前,尽管他接受了美国的援助,但对这些援助金额微乎其微,不足以解释台湾经济的爆炸式增长。经济统计数据永远无法完全展现共产党胜利给中国人民带来的悲剧,但它们确实揭示了一些重要信息。共产党推行农业集体化,如今大陆的人均大米产量低于革命前。蒋中正向地主购买土地,并将土地分配给农民。原地主将大部分资金投资工业,且政府则鼓励外商投资。如今,台湾的人均收入是大陆的五倍(实际远不止五倍)。台湾的1800万人出口额比大陆的10亿人还高出约50%。


大量的“经济学家”在分析台湾经济起飞时,总是把美援描述为经济成长的核心因素;很多相关的书籍,包括现今台湾本土的出版物,都在夸大美援的作用;简中书籍文章更是故意误导读者,甚至把国府迁台时带走的黄金描述成关键因素。而处于美援中的核心人物尼克松,却认为美援微不足道,台湾早期的繁荣绝不能被简单归功于“美国给钱”。

尼克松1953至1961年担任美国副总统,正是这段时间,是美国援助中华民国的黄金期,是台湾经济从贫弱到起飞的关键时期。很多美国援助法案,都有其本人积极参与,他掌握了很多第一手数据。此后,他在1968-1974年出任美国总统,成了第一把手,对台政策他本人就是决策人。最关键的是,他在写《Leaders》这本回忆录时,已经是1980年代,因水门事件已离开政治多年,早已不担任任何公职,这种回头看的方式,使得他更加冷静与客观,更带有全局性的视野。

显然,尼克松认为,促成台湾经济繁荣最根本的因素,绝不是美援,而是蒋中正一而贯之的保守主义理念在台湾得到了实施。事实也证明,1965年6月30日美援正式停止后,台湾的增长反而更加迅猛。这有力地证明了增长的动力源源不断来自于内部制度,而非外部输血。如果仅仅靠援助就能产生经济奇迹,那么二战后接受美援更多的菲律宾、南越甚至许多拉美国家,却没有一个能复刻台湾的成功。很显然尼克森认为:援助是“外因”,而制度驱动的增长才是“内因”。

字体子集化优化在线动态渲染PDF

最近做了一个在线生成PDF,适时预览并可在线打印的系统。使用了pdf-lib.js(https://pdf-lib.js.org),作为前端创建PDF的框架,虽然很方便,但遇到一个棘手的问题:如何解决中文显示。

PDF文件不同于web文件(HTML+CSS),它的字体是嵌入文件的,而由于安全性和PDF文件本身机制的问题,并不能读取本地字体文件。而国际PDF阅读器规范中的 “Standard 14 Fonts”(14 种标准字体)中并没有中文字体,这就导致了在不嵌入中文字体的情况下,出现中文就会无法渲染。

Standard 14 Fonts

内置的 14 种标准字体 这 14 种字体全部属于 拉丁字母(英文) 系列,分为四大类:
1.无衬线 (Sans Serif)字体: Helvetica, Helvetica-Bold, Helvetica-Oblique, Helvetica-BoldOblique
2.衬线 (Serif/Roman) 字体:Times-Roman, Times-Bold, Times-Italic, Times-BoldItalic
3.等宽 (Monospace)字体: Courier, Courier-Bold, Courier-Oblique, Courier-BoldOblique
4.符号 (Symbol) :Symbol, ZapfDingbats

PDF 的设计初衷是 “所见即所得” (WYSIWYG)。它的目标是:不管你把这个文件发给谁,在手机上、打印机上还是 20 年后的电脑上,看到的排版必须一模一样。

封闭性:PDF 不信任阅读者的系统。它认为:“万一对方电脑里没有微软雅黑,我的排版不就乱了吗?”

机制:为了保证绝对一致,pdf-lib 必须执行 “字体嵌入 (Embedding)”。它需要把字体文件的每一个二进制数据“缝进” PDF 文件里。

面临的难点

这个系统需要兼容正体中文(繁体)和简体中文,而这种字体体量大得惊人。兼容性最好的Adobe全字符体——Super OTC 体积高达100M+,师出同门的Google Noto也差不多这个体量,如放到Web项目,简直是灾难,浏览器瞬间会被卡死。

于是只能放弃使用这种大字符集的字体,选择性地支持正体或简体。

但是单独的简体字体,体积也很大,思源Source Han Serif,单独一种字重的字体,也高达20M+,Noto也要10M-20M。如果要加载这么大的字体,配置一般的电脑尤其是内存小的电脑,会频繁出现假死的情况。

于是,只能想办法减少字体的体积。

通过万能的Gemini,终于有了解决办法:字体子集化。

说白了,就是从原字体中提取一部分字符,只要能覆盖自己常用的字符就行了。

方案:

1. 用集成工具做子集化。这是最常用的方式,工具例如,Fontmin(https://ecomfe.github.io/fontmin/)。

这种方式就是要准备“字体白名单”,也就是你要把那些你需要的字符一一列出来,让它把你需要的字符从庞大字库中“抠”出来。

可以到GitHub上下载常用中文字符3500字等整理好的字符集,导入Fontmin中。也可以自己整理用到的文字再加进去。

2.用 Python 做字体子集化。

#安装fonttools库
pip install fonttools brotli

#命令执行子集化
pyftsubset original.ttf --text-file=chars.txt --output-file=sub.woff2 --flavor=woff2
'''
其中
original.ttf:原始字体,如思源宋体
--text-file:字符白名单文件
--output-file输出字体
'''

#不指定字符白名单,只按照某个标准来子集化(如变成GB2312标准字符集)
pyftsubset NotoSerifSC-Medium.ttf --unicodes="U+0020-007E,U+00A0-00FF,U+2000-206F,U+3000-303F,U+4E00-9FA5" --output-file=label_gb2312.ttf --layout-features='*'

3.在线动态字体子集化

① Node.js 生态方案:Fontmin,基于 fonteditor-core,支持 TTF、EOT、WOFF、WOFF2 之间的转换。它支持插件机制,可以方便地动态剪裁。示例代码:

const Fontmin = require('fontmin');

const fontmin = new Fontmin()
    .src('fonts/SourceHanSansCN-Regular.ttf') // 原始 15MB 字体
    .use(Fontmin.glyph({
        text: '张三的PDF发票金额: ¥100.00' // 前端传过来的动态文本
    }))
    .use(Fontmin.ttf2woff2()) // 转换为更小的 woff2 格式
    .dest('dist/fonts');

fontmin.run((err, files) => {
    // 这里的 files[0].contents 就是剪裁后只有几 KB 的字体二进制流
});

西安事变,一场分裂的联合阴谋,中国历史倒退的悲剧

掩盖罪恶的谎言

彻底改变中国命运走向的西安事变,经过诸多学者的挖掘,真相早已大白。中国大陆,共党所编造的“教科书”对这段历史颠倒黑白的描述,不过是洗脑和掩盖罪恶的手段。西安事变自始至终都与“爱国”“抗日”毫无关系,不过是张与共党的各怀鬼胎的苟合,企图背靠苏俄,在西北占山为王,成立分裂中国的割据政权。

今天是西安事变89年。1936年12月12日,张杨发动震惊中外的西安事变,彻底改变了中国历史的走向。当时已被宣判死刑的共党得以苟延,从此在全国浴血抗战的大背景下,却一心躲在深山和敌后扩张坐大,并与日军秘密勾结背刺血战抗日的国军,为日后全面赤化中国大陆积蓄力量。中国人的命运,陡然在13年后进入近代史最黑暗、残酷和恐怖的时期,延续至今七十多年。

大陆的历史“教科书”里,讲述的这个“伟大”的“爱国”政变,不过是彻头彻尾的谎言。张杨这两个妄人,也被塑造成了“爱国将领”。颠倒黑白的伪史,不过是洗脑的目的。

一. 张学良发动西安事变,本意是效仿盛世才,割据西北,根本就不是为了所谓的“抗日”

2013年3月20日,一批和西安事變有關的秘密文件在紐約邦瀚斯(Bonhams)拍卖行拍賣,这批文件的是一个叫做海岚·里昂(Hyland L. Lyon)的美国人所有,他曾擔任張學良飛機駕駛員、機械師,他於1941年離開中國後,帶著個人行李、照片,以及受張家所托儲存私密物件的保險箱回到美國。据斯坦福大学胡佛研究所研究员郭岱君说,胡佛研究所能出的最高价为十万美元,竞不过出二十多倍高價(二百多万美元)的中共陕西西安文管所,最后被后者买走。

 

邦瀚斯(Bonhams)官网展示的部分文件

链接地址:https://www.bonhams.com/auction/21070/lot/3/chinese-communist-party-mao-zedong-zhou-enlai-et-al-holograph-letter-in-an-unknown-hand-with-secretarial-signatures-of-mao-zedong-zhou-enlai-bo-gu-and-zhang-wentian-6-pp-8vo-np-august-9-1936-an-18-point-letter-addressed-to-zhang-xueliang-outlining-a-strategy-to-convince-chiang-kai-shek-to-cooperate-with-communist-forces/

BBC的报道原文:https://www.bbc.com/zhongwen/trad/china/2013/03/130321_xian_incident_auction

共党官网的报道原文:http://dangshi.people.com.cn/BIG5/n/2013/0321/c85037-20868868.html