深入剖析 JavaScript 核心特性:从基础到实战 🚀

72 阅读5分钟

JavaScript 作为前端开发的基石,其核心特性决定了代码的运行机制与行为逻辑。本文将从严格模式、this 指向、变量提升、函数声明等核心概念入手,结合实战代码案例,逐点拆解细节,帮助你构建清晰的知识体系。

一、严格模式:让 JS 更 “守规矩” 💻

严格模式("use strict")是 ES5 引入的一种代码约束机制,通过消除语言的不合理特性、增强安全性,让代码更严谨。

1.1 严格模式的启用方式

  • 全局启用:在脚本顶部添加 "use strict";
  • 局部启用:在函数内部顶部添加,仅约束当前函数(避免污染全局)。
// 全局严格模式
"use strict"; 
var b = 10;
(function b(){
    b = 20; // 不生效(函数名只读)
    console.log(b); // 输出函数本身:f b() {...}
})()

1.2 严格模式的核心作用

  1. 消除不合理行为

    • 禁止隐式全局变量(未声明的变量赋值会报错,非严格模式下会自动挂到顶层对象)。
    • 禁止删除变量 / 函数(delete b 会报错,非严格模式下无效但不报错)。
  2. 增强安全性

    • 禁止函数内部修改函数名(函数名在函数体内是只读局部变量,如上面中的 b=20 不生效)。
    • 严格模式下,普通函数调用时 this 指向 undefined(非严格模式指向 window,见下文 this 部分)。
  3. 提升性能与兼容性

    • 编译器可优化代码(减少动态类型判断),提升运行速度。
    • 禁止未来版本可能移除的语法(如 with 语句),为升级铺路。

1.3 实战易错点

  • 函数名只读特性:在严格模式下,函数体内的函数名是 “常量”,赋值会报错 Assignment to constant variable
  • 全局变量与顶层对象分离:严格模式下,var 声明的全局变量不再自动挂到 window(非严格模式会挂载)。

二、this 指向:谁调用,指向谁 🎯

this 是函数执行时自动生成的 “调用者指针”,其指向完全由调用方式决定,与声明位置无关。

2.1 普通函数调用(非对象方法)

  • 非严格模式this 指向顶层对象(浏览器为 window,Node 为 global)。
  • 严格模式this 指向 undefined
<!-- 非严格模式 -->
<script>
var name = '小王';
function func(){
    console.log(this); // window
    console.log(this.name); // 小王
}
func(); // 等价于 window.func(),this 指向 window
</script>

2.2 对象方法调用

函数作为对象的属性被调用时,this 指向当前对象(调用者)。

<script>
"use strict"
var name = "windowsName";
var a = {
    name:'小娄',
    fn:function(){
        console.log(this); // {name: '小娄', fn: ƒ}
        console.log(this.name); // 小娄
    }
}
a.fn(); // 调用者是 a,this 指向 a
</script>

注意:若方法被赋值给变量后调用,this 会丢失原对象指向:

var b = a.fn; 
b(); // 此时是普通函数调用,严格模式下 this 为 undefined(非严格模式指向 window)

2.3 构造函数调用(new 关键字)

用 new 调用函数时,this 指向新创建的实例对象

<script>
function Person(name,age){
    this.name = name; // this 指向新实例 p
    this.age = age;
}
const p = new Person('labubu',2);
console.log(p.name); // labubu(实例属性被正确赋值)
</script>

2.4 事件处理函数

DOM 事件回调中,this 指向触发事件的元素

<input type="text" id="inp"/>
<script>
document.getElementById('inp').addEventListener('keydown',function(){
    console.log(this); // <input type="text" id="inp"/>(当前输入框元素)
    console.log(this.value); // 输入框中的值
})
</script>

2.5 箭头函数:没有自己的 this ⚠️

箭头函数不绑定 this,其 this 继承自外层作用域的 this(静态绑定,声明时确定)。

<script>
var name = "windowsName";
var a = {
    name:'Tom',
    func1:function(){
        console.log(this.name); // Tom(this 指向 a)
    },
    fun2:function(){
        // 外层作用域 this 指向 a
        setTimeout(() => {
            this.func1(); // 正确调用(this 继承自 fun2 的 this)
        },1000)
        // 若用普通函数:this 指向 window,会报错
        // setTimeout(function(){ this.func1() },1000) // 报错
    }
}
a.fun2(); // 1秒后输出 Tom
</script>

三、变量提升:JS 引擎的 “预编译” 机制 🔄

变量提升是 JS 引擎在编译阶段的特性:var 声明的变量和函数声明会被 “提前” 到作用域顶部,但赋值留在原地。

3.1 变量提升的底层逻辑(文档 2+3)

  • 编译阶段:引擎扫描代码,将 var a 提升到当前作用域顶部(仅声明,不赋值)。

  • 执行阶段:从顶部开始执行,赋值操作在原位置执行。

// 示例:变量提升
console.log(a); // undefined(声明被提升,赋值未执行)
var a = 1;
console.log(a); // 1(赋值执行后)

3.2 函数声明 vs 变量声明:函数优先级更高

函数声明会被完整提升(包括函数体),且优先级高于变量声明。

// 隐含逻辑
var b = 10; // 变量声明(提升后被函数声明覆盖)
(function b(){ // 函数声明(完整提升,优先级更高)
    console.log(b); // 输出函数本身,而非外部变量 10
})()

3.3 全局变量与顶层对象

  • 浏览器环境:非严格模式下,var 声明的全局变量会挂到 window 上(let/const 不会)。

    <script>
    var a = 1;
    console.log(window.a); // 1(var 全局变量 → window 属性)
    let b = 2;
    console.log(window.b); // undefined(let 全局变量在 Script 块作用域)
    </script>
    
  • Node 环境:顶层对象是 globalvar 全局变量挂到 global 上。

    // Node 环境
    var a = 1;
    console.log(global.a); // 1
    

四、函数声明:函数名的 “只读” 特性 📜

函数声明在函数体内是只读局部变量,无法被重新赋值(严格模式下会报错)。

4.1 实战案例

"use strict";
var b = 10;
(function b(){
    b = 20; // 严格模式下报错:Assignment to constant variable
    console.log(b); // 若非严格模式,输出函数本身(赋值无效)
})()
  • 原因:函数名在函数体内被视为 “只读常量”,即使 JS 是弱类型语言,也不允许修改。

总结:核心知识点梳理 📝

特性核心要点
严格模式约束语法、禁止不合理行为、this 指向 undefined(普通函数)、函数名只读
this 指向普通调用→window/undefined、对象方法→对象、new→实例、箭头函数→继承外层
变量提升var 和函数声明被提升,函数优先级高于变量,let/const 无提升(有 TDZ)
函数声明函数名在体内只读,严格模式下赋值报错

掌握这些特性,能帮你避开 80% 的 JS 坑!如果有疑问,欢迎在评论区交流讨论哦 😊~