JS炼化 :(this+new+构造函数)面向对象秘法包——从抽象到落地“焚诀”来了

0 阅读9分钟

读完秘法包不会用?焚诀来了

上一篇我们用**剑(this)、剑鞘(new)、剑法(构造函数)**的比喻,理解了三者的本质关系。 本篇目标:把零散的“剑意”合成完整的“焚诀”,从概念落地到运行逻辑,吃透面向对象底层根基

先简单回顾一下秘法包

  • this 是剑:操作对象、访问实例属性的核心工具
  • new 是剑鞘:保证 this 正确指向实例,启动构造函数
  • 构造函数是剑法:定义对象模板,批量创建同类对象

详情看上一篇秘法包基础解析,下面开始修炼焚诀

焚诀导读(焚诀修炼结构)

1. 铸剑基础 • this 常见场景(先认识)

2. 剑之本意• this 面向对象核心(重点练)

3. 剑鞘认主 • new 到底做了什么(核心)

4. 剑法定式 • 构造函数完整用法(核心)

5. 焚诀合一 • 剑·鞘·法三者联动(本篇灵魂)

焚诀修炼开始

第一重 · 铸剑基础(this基础场景)

定位:了解即可 / 说明:this的使用场景较多,先梳理非面向对象的基础场景,建立基础认知即可,无需死抠细节,后续核心内容才是修炼重点。

1. 全局作用域中的this
  • 规则:浏览器环境指向 window ,Node.js环境指向 global ,严格模式下为 undefined 
console.log(this); // 浏览器:window / Node:global
'use strict';
console.log(this); // 严格模式:undefined
2. 普通函数调用中的this
  • 规则:非严格模式默认指向全局对象,严格模式下为 undefined 
function fn() {
  console.log(this);
}
fn(); // 非严格模式:window / 严格模式:undefined
3. 箭头函数中的this(箭头函数很神,但是面向对象不合适)
  • 规则:不绑定自身this,继承外层作用域的this指向,这是与普通函数的核心区别
const obj = {
  name: '张三',
  sayName: () => {
    console.log(this.name); // 继承外层全局this,浏览器下指向window
  }// obj 的 {} 是对象字面量,不产生作用域
};
obj.sayName(); // 输出:undefined
4. call / apply / bind显式绑定this
  • 规则:可手动强制修改this指向,优先级高于默认绑定,提升代码灵活性
function fn() {
  console.log(this.name);
}
const obj = { name: '李四' };
fn.call(obj);   // 手动绑定,输出:李四
fn.apply(obj);  // 效果同call,输出:李四
const boundFn = fn.bind(obj);
boundFn();      // 永久绑定,输出:李四

 

第二重 · 剑之本意(this面向对象核心)

定位:重点掌握 说明:抛开基础场景,面向对象中this的指向逻辑极其清晰,只有两个核心场景,也是后续写代码最常用的部分,必须吃透。

1. 对象方法调用中的this
  • 规则:this指向调用该方法的所属对象,谁调用方法,this就归属谁
const obj = {
  name: '前端学习者',
  sayName() {
    console.log(this.name); // this指向调用方法的obj对象
  }
};
obj.sayName(); // 输出:前端学习者
2. 构造函数 / new调用中的this
  • 规则:this指向new创建的新实例对象,也就是剑认主的核心逻辑,this通过new找到自己的归属
function Person(name) {
  this.name = name; // this指向new创建的新实例,剑找到新主人
}
const p = new Person("张三");
console.log(p.name); // 输出:张三

 

this使用注意事项

  • 对象方法作为回调函数时,this指向易改变→用箭头函数、bind绑定或缓存 const self = this 修正指向。(这个可能有些绕,但是还是this的核心机制:this  的指向 不是由「函数定义的位置」决定的,而是由「函数被调用的方式」决定的,也就是谁调用了这个函数, this  就指向谁(箭头函数除外,它是继承外层作用域的 this) 一句话就是:谁拿起this这把剑来用,剑就听谁的指挥,就为谁服务。你也可以用 call / apply / bind 提前给剑认主,不管谁拿,剑只听你指定的那个人的话。
  • 嵌套函数中this易混乱→借助箭头函数继承外层this,或显式绑定明确指向
  • 严格模式下this默认指向undefined→规范绑定对象,避免无绑定调用

 

第三重 · 剑鞘认主(new完整知识点)

定位:核心重点 说明:new是连接构造函数与this的关键,更是剑认主的核心仪式,没有new,剑法无法施展,剑也没有归属,彻底吃透它的执行逻辑,才算掌握面向对象的核心钥匙。

1. new操作符的核心作用

核心:new就是一场认主仪式,先造主人,再让剑(this)认主,最后按剑法武装出一个完整实例。

本质:是创建构造函数的实例对象,稳定绑定this,执行构造函数逻辑,最终返回可使用的完整实例。

2. new执行的4件事(比喻+实际作用一一对应)
2.1. 造一个新主人(创建空对象)

比喻:打造一个全新的、无属性的主人肉身

实际:创建一个空的JavaScript对象 {} ,这个空对象就是未来的实例载体

2.2. 给主人归入门派(关联构造函数原型)

比喻:给新主人打上剑法的门派标记,继承门派里的公共功法

实际:将空对象的  proto 指向构造函数的 prototype 属性,为后续继承公共方法打下基础,无需重复创建方法

(早期只用  this  和  new  创建对象时,每个实例都会重复携带方法,内存占用大、不好管理。 于是就有了原型(prototype),相当于一个门派,把共用方法统一存放。 实例归入门派,就能共享所有公共方法,节省内存、方便维护。 这一步就是把空对象关联到构造函数原型,更详细的原型机制我们后面再学。)

2.3. 剑认主:把this绑定给新主人(最核心一步)

比喻:剑鞘扣紧,将无主的剑(this)正式交给新主人,完成认主仪式

实际:构造函数里的this原本没有固定归属,new在这一步强制将this绑定给刚创建的空对象,从此this只归属这个实例,完美对应“this通过new认主”

2.4. 按剑法武装主人,再把主人交出来(执行构造、返回实例)

比喻:按照剑法招式,给主人装备专属属性、武器,打造完整的修炼者

实际:运行构造函数内的代码,通过this给实例添加名字、年龄等属性和方法,若构造函数无返回对象,就将这个武装完成的实例返回出去

3. new代码示例+手动模拟实现
// 构造函数(剑法)
function Person(name, age) {
  this.name = name;
  this.age = age;
}
// 门派公共功法(原型方法)
Person.prototype.sayHi = function() {
  console.log(`Hi, I'm ${this.name}`);
};

// 执行认主仪式(new调用)
const p = new Person('张三', 18);
p.sayHi(); // 输出:Hi, I'm 张三

// 手动模拟认主仪式(模拟new)
function myNew(constructor, ...args) {
  // 1. 造新主人肉身
  const obj = {};
  // 2. 归入门派
  obj.__proto__ = constructor.prototype;
  // 3. 剑认主,绑定this并执行剑法
  const result = constructor.call(obj, ...args);
  // 4. 交出完整主人
  return result instanceof Object ? result : obj;
}

// 测试模拟new
const p2 = myNew(Person, '李四', 20);
p2.sayHi(); // 输出:Hi, I'm 李四
 

new使用注意事项

  • 构造函数必须配合new使用,省略new会让构造函数变成普通函数,this指向全局,无法完成认主→构造函数首字母大写,养成配合new调用的习惯
  • 构造函数中手动返回对象,会覆盖new创建的默认实例,认主失效→无特殊需求,不手动返回数据,依靠new自动返回实例

 

第四重 · 剑法定式(构造函数完整知识点)

定位:核心重点 说明:构造函数是剑法的定式,是批量打造主人的模板,掌握规范写法,才能高效创建同类型对象。

1. 构造函数的本质与作用

本质:ES5中JavaScript实现面向对象编程的基础形式,专门用于创建对象

作用:定义对象的通用属性和方法,作为固定剑法模板,通过new调用批量创建实例

2. 构造函数的编写规范
  • 命名规范:首字母大写,与普通函数区分,行业通用约定
  • 赋值方式:通过this为实例添加属性和方法,借助剑认主的逻辑完成属性绑定
  • 返回值:无需手动return,new会自动返回完成认主的完整实例
3. 构造函数基础代码示例
// 基础剑法(构造函数)
function Person(name, age) {
  this.name = name;
  this.age = age;
  this.sayHi = function() {
    console.log(`Hi, ${this.name}`);
  };
}

// 执行认主仪式,创建两个主人
const p1 = new Person('张三', 18);
const p2 = new Person('李四', 20);

// 主人使用自身剑法
p1.sayHi(); // 输出:Hi, 张三
p2.sayHi(); // 输出:Hi, 李四
4. 构造函数与普通函数核心区别
  • 调用方式:构造函数必须用new调用,普通函数直接调用即可
  • this指向:构造函数中this指向new创建的实例,普通函数中this指向全局或undefined
  • 命名规范:构造函数首字母大写,普通函数小写开头
  • 主要作用:构造函数批量创建对象,普通函数执行单一逻辑、返回运算结果
  • 返回值:构造函数自动返回实例,普通函数需手动return结果
5. 抛出思考(引向下一篇)

当前基础写法能实现功能,但存在一个问题:每new一个实例,构造函数内的方法就会重新创建一次,p1和p2的sayHi功能完全一致,却占用多份内存,实例越多浪费越严重?

有没有办法让所有实例共用一套公共方法,不重复创建?这就是下一篇要探究的原型&原型链,以及ES6 class语法糖的优化逻辑。

 

第五重 · 焚诀合一(剑·鞘·法三者联动)

定位:本篇灵魂 说明:三者绝非独立存在,而是一套完整的焚诀功法,协同工作才能发挥最大作用,这是JS面向对象的核心逻辑。

1. 三者协同执行流程

一句话总结执剑鞘(new),运剑法(构造函数),剑(this)认主归位,最终炼成完整主人(实例)。 用new启动构造函数,先创建空实例,再将this绑定到该实例,执行构造函数为实例赋值,最终返回完整可用的实例。

2. 完整联动核心代码
// 剑法(构造函数):定好修炼定式
function Person(name) {
  // 剑(this):等待认主,为主人赋值
  this.name = name;
  this.sayName = function() {
    console.log(this.name);
  };
}

// 剑鞘(new):执行认主仪式,启动剑法
const p = new Person('张三');

// 主人(实例):使用自身的剑施展功法
p.sayName(); // 输出:张三

3. 联动核心总结

  • 构造函数(剑法):定下对象的基础规则,是功法核心
  • this(剑):负责实例数据传递,是操作对象的工具
  • new(剑鞘):完成认主仪式,保障this指向稳定,是功法启动器 三者缺一不可,配合使用才构成JS面向对象的基础,后续所有进阶知识,都围绕这一核心逻辑展开。

到这一步焚诀就大成了,只差修炼和优化了

学习复盘心得小小分享

其实不管学什么,刚开始的路都是又乱又零散。 回想刚学 JS 的那段时间,基础知识点,作用域、函数、闭包、this 一个个学过来, 知识点全都拼不起来,代码也看不懂,感觉知识学历和没有学一样,越学越迷茫,越学越煎熬。

直到今天回头复盘、把整条线梳理清楚才明白: 那些曾经看似无关又折磨的内容,并不是孤立的知识点, 最后拼装成了 JavaScript 最底层、最核心的运行框架。

虽然现在依然离精通很远,未来的学习也不会轻松, 但至少方向彻底清晰了,心里也有底了。 地基打牢,后面的路再难,也知道该怎么走,该往哪儿走。 踏踏实实继续往前走,就很好。

学习分享,如果有理解不对的地方,欢迎大家指正,一起学习进步