js变量提升

js变量提升

堆栈内存 以及 基本&引用数据类型

基本数据类型&引用数据类型

浏览器加载我们js时候,首先会形成一个全局作用域window提供一个代码自上而下执行的环境;

  1. 引用类型会在作用域外 新开辟一块内存空间(有一个16进制地址),键值对依次存储到这个内存中;基本数据类型是直接在作用域开了一个位置就存了。

  1. 想让代码执行就得有一个执行的环境,所以函数执行首先都会形成一个私有的作用域。

作用域:

  1. 提供代码自上而下执行的环境

  2. 存储基本数据类型,所有基本数据类型都是直接在该作用域开辟一个位置

栈内存:即作用域

堆内存:存储引用数据类型

释放内存,让其不被占用,arr=null,

变量提升机制

在代码自上而下执行之前,浏览器会把带var或者function关键字的进行“声明”或“定义”,这就叫变量提升

变量提升只发生在当前作用域

私有作用域的变量提升和全局基本一致。私有作用域下的这些变量也就是私有变量,那我们就把保护私有作用域下的私有变量叫做闭包。

带var和不带var

全局的var变量和window属性存在映射关系

不加var:添加了window的一个属性

私有作用域

带var:私有变量,跟外界没有关系

不带var:就会向上级作用域查找,“作用域链”机制

console.log(a,b); // undefined undefined
var a = 12,b=12;

function fn(){
    console.log(a,b); // undefined 12
    
    var a=b=13;
    console.log(a,b) // 13 13

}
fn();
console.log(a,b); // 12 13

function fn(){
    b=13;
    console.log(b) // 13

}
fn();
console.log(b) // 13
console.log(window.b) // 13

提升的一些细节问题

函数表达式和普通函数的区别

普通函数:用function关键词来处理的

函数表达式:只对函数左边进行变量提升

console.log(fn);
fn() // Uncaught TypeError: fn is not a function
sum()

var fn=function(){
    console.log(1)
}
function sum(){
    console.log(2)
}

条件判断下的变量提升

当前作用域下,不管条件是否成立,都要进行变量提升

console.log(a) // undefined
if(1===2){
    var a = 2;
}
console.log(a); // undefined
// 另一种情况
console.log(a)
if('a' in window){
    var a = 100;
}
console.log(a);

function的一道题

  • 全局下没有变量提升(自执行没有名字所以也没有变量提升)。

window.f = ...

window.g = ...

  • 自执行函数部分:

创建一个函数并且把它执行了。只要是函数执行,肯定会形成一个私有作用域。

变量提升:带function的也只剩声明了g,但没有定义。私有作用域中声明一个变量是私有的,跟全局作用域是没有关系的。

  • [] -> []==false -> 0==0

f = function(){ return true; };
g = function(){ return false; };
(function(){
    console.log('---');
    console.log(window.g);
    function g(){ return true; };
    if(g() && [] == ![]){
        console.log('panduan');
        f = function(){ return false; }
        function g(){ return true; };
    }
})();
console.log(f());
console.log(g());

这里还有块级作用域

console.log(fn);
// if(1===2) 那么结果又不一样 undefined
if(1===1){
    console.log(fn);
    function fn(){
        console.log('ok');
    }
}
console.log(fn);

但是这里又不是完整的块级作用域,因为这个fn还是全局的。

重名问题的处理

重名时会重新赋值不会重新声明

fn(); // 4
function fn(){ console.log(1) };
fn(); // 4
function fn(){ console.log(2) };
fn(); // 4
var fn = 100;
fn(); // Uncaught TypeError: fn is not a function
function fn(){ console.log(3) };
fn(); // Uncaught TypeError: fn is not a function
function fn(){ console.log(4) };
fn();

题外话

let不存在变量提升

let/const不存在变量提升。

let a=6;
console.log(a); // 6
console.log(window.a); // undefined 不存在映射机制的

语法检测:

es6机制下,代码执行之前首先会做语法检测。

  1. 重复定义的会报错

  2. 并且它说,这些定义的变量在正式定义之前是不能使用的。

// 这个例子很好
// 全局 a,b,fn
// fn执行形成一个私有作用域:let a,所以用a只能用在创建a的后面;b不是let,这里没有出现b,往上级去找
let a=10,b=10;
let fn=function(){
    // console.log(a,b);
    let a = b=20;
    console.log(a,b);
}
fn();
console.log(a,b);

a=3;
let a=8;
console.log(a);

暂时性死区

总结:

首先先形成一个栈内存全局作用域,或私有作用域私有栈内存,在私有作用域下也会先验证它是不是私有变量,如果是的话就是自己的,如果不是则向上级作用域查找。

代码执行之前会做很多事情:

老规范会对变量进行提前声明或者定义,则按照变量提升机制走,新规范重复检测机制。

let 会形成一个块级私有作用域,同上面函数作用域一样,在定义之前不能使用。

// 题目
var a=12;
if(true){
    console.log(a); // 同理,这里使用也报错
    let a=13;
    console.log(a);
}
console.log(a);

// 这是typeof的一个bug
console.log(typeof a); // undefined

javascript 暂时性死区_Novice-XiaoSong的博客-CSDN博客_js暂时性死区

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值