var、let、const、this

博客围绕JavaScript展开,介绍了var和let的区别,包括作用域不同,var为函数作用域,let是块作用域,且访问未声明变量时提示不同;阐述了this在全局、函数、类上下文的指向,以及axios回调函数中this指向问题;还说明了call()、apply()、bind()改变this指向的作用和区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、var let 区别

Js 作用域:全局作用域、函数作用域、块作用域(es6);
1、作用域不同: var 函数作用域;let、const 块作用域

相关参考:JS中全局作用域与局部作用域的理解    深入理解js的变量提升和函数提升

/*var 函数作用域
 * if、for属于块作用域  
*/
if(true) { var a = 3;}
console.log(a); // 3
for(var i=0; i<4; i++) {
	var b = 5;
};
console.log(i);	// 4 
console.log(b); // 5

/*let 块作用域*/
if(true) { let a = 3;}
console.log(a); // Uncaught ReferenceError: a is not defined
for(let i=0; i<4; i++) {
	var b = 5;
};
console.log(i);	// Uncaught ReferenceError: i is not defined
console.log(b); // 5

2、var 在变量声明之前访问提示 undefined,let 则直接提示 ReferenceError

ReferenceError、TypeError:引用错误和类型错误区别

作用域区别:ReferenceError在作用域中找不到;TypeError在作用域中找到了但是做了它不可能做的事情

二、this 详解

this: 当前执行上下文(global、function 或 eval)的一个属性,在非严格模式下,总是指向一个对象,在严格模式下可以是任意值。

1.全局上下文(global): 指向全局对象

// 在浏览器中, window 对象同时也是全局对象:
console.log(this === window); // true

let a = 37;
console.log(window.a); // 37

2.函数上下文(function):取决于函数被调用的方式

  // 2.1 非严格模式
  function f1(){
    return this;
  }
  //在浏览器中:
  f1() === window;   //在浏览器中,全局对象是window
  
  // 2.2 严格模式
  function f2(){
   "use strict"; // 这里是严格模式
    return this;
   }
   // 函数直接调用
   f2() === undefined; // true
   
   // 作为对象的属性或方法调用
   window.f2() === window; // true

   
   // 2.3示例: 对象可以作为 bind 或 apply 的第一个参数传递,并且该参数将绑定到该对象。
   var obj = {a: 'Custom'};

   // 声明一个变量,并将该变量作为全局对象 window 的属性。
   var a = 'Global';
   function whatsThis() {
    return this.a;  // this 的值取决于函数被调用的方式
   }
   whatsThis();          // 'Global' 因为在这个函数中 this 没有被设定,所以它默认为 全局/ window 对象
   whatsThis.call(obj);  // 'Custom' 因为函数中的 this 被设置为obj
   whatsThis.apply(obj); // 'Custom' 因为函数中的 this 被设置为obj

3.类上下文(eval)

与在函数中类似,因为类本质上也是函数,但也有一些区别和注意事项

  // 类中所有非静态的方法都会被添加到 this 的原型(静态方法不是 this 的属性,它们只是类自身的属性)
  class Example {
    constructor() {
      const proto = Object.getPrototypeOf(this);
      console.log(Object.getOwnPropertyNames(proto));
    }
    first(){}
    second(){}
    static third(){}
  }
  new Example(); // ['constructor', 'first', 'second']

4.axios 的回调函数中 this 不指向vue实例,为 underfind

   详见: axios的回调函数中this不指向vue实例,为undefined

相关参考:  this-MDN  

三、call()、apply()、bind()

作用:用来改变this的指向
区别:
  obj.myFun.call(db, param1,...,paramN);
  obj.myFun.apply(db, [param1,...,paramN]);
  obj.myFun.bind(db,'param1,...,paramN)(); // bind返回的是函数

相关参考:  call()、apply()、bind()的区别

### JavaScript 中 `var`、`let` 和 `const` 的区别 #### 1. **作用域** - 使用 `var` 声明的变量具有函数作用域或全局作用域。如果在函数外部声明,则该变量属于全局作用域;如果在函数内部声明,则它仅限于当前函数的作用域[^1]。 - 使用 `let` 或 `const` 声明的变量则具有块级作用域(block scope)。这意味着这些变量仅在 `{}` 所定义的范围内有效,无论是循环体还是条件语句内。 #### 2. **重复声明** - 如果尝试在同一作用域下多次使用 `var` 声明同一个变量名,JavaScript 不会报错,而是覆盖之前的声明[^3]。 - 对于 `let` 而言,在同一作用域中重新声明相同的变量会导致语法错误。 - 同样地,对于 `const` 来说,一旦声明了一个常量,就不能再对该名称进行重新赋值或者再次声明。 #### 3. **初始化需求** - 变量通过 `var` 关键字可以先声明后赋值,甚至不赋初始值也无妨。 - 利用 `let` 定义变量同样允许延迟初始化。 - 然而,采用 `const` 创建的是不可变绑定,因此必须立即赋予固定值,并且后续不能再改变这个值。 #### 4. **变量提升 (Hoisting)** - 当程序运行时,所有由 `var` 声明的变量都会被提前处理并设置为 `undefined` ,这就是所谓的 “变量提升”现象[^2]。 - 相反,那些经由 `let` 或者 `const` 引入的新实体不会经历这样的过程——直到执行流真正到达它们各自的声明处之前都是暂时性的死区(TDZ),在此期间试图访问未初始化的数据将会抛出 ReferenceError 错误。 ```javascript console.log(xVar); // 输出 'undefined' console.log(xLet); // 抛出 ReferenceError: Cannot access 'xLet' before initialization console.log(xConst); // 抛出 ReferenceError: Cannot access 'xConst' before initialization var xVar = 5; let xLet = 6; const xConst = 7; ``` #### 推荐使用的顺序 基于上述特性差异以及现代编码实践考虑,推荐按照如下优先级选用合适的关键词来完成相应的编程任务: 优先选择 `const` > `let` > `var` 。这是因为尽可能减少不必要的可变状态有助于构建更健壮的应用程序逻辑结构。 --- ### 示例代码展示不同之处 下面是一些简单的例子用来说明这三种方式之间存在的主要差别: ```javascript // var example with function and block scoping issues. function checkScope() { var color = "blue"; if (true){ var color = "green"; console.log('Inside Block:',color); } console.log('Outside Block but Inside Function:',color); } checkScope(); // Both logs will show green because of hoisting within the same functional scope. // let respects block level scopes properly unlike var does here above. for(let i=0;i<3;i++) {setTimeout(() => console.log(i),1);} // This prints numbers from 0 to 2 correctly due to individual copies per iteration created via block scoped variable i declared using let keyword inside loop construct body itself rather than shared single instance across all iterations as would happen had we used var instead there too! try{ const piValue=Math.PI; }catch(err){console.error(`Caught Exception:${err.message}.`)} finally{piValue=3;} // Error thrown since reassignment isn't allowed after first assignment when defining constants through const statement form. ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值