(编辑:jimmy 日期: 2024/12/28 浏览:2)
预解析也叫预声明,是提前解析声明的意思;预解析是针对变量和函数来说的;但是变量和function的的预解析是两套不同的机制;
var a=1
var num; //1、声明(declare):var num; ->告诉浏览器在当前作用域中有一个num的变量了,如果一个变量只是声明了但是没有赋值,默认的值是undefined console.log(num);//->undefined num = 12; //2、定义(defined):num=12; ->给我们的变量进行赋值 console.log(num);//->12 //变量提前使用的话,就是undefined console.log(testStr);//undefined var testStr="22222222"
function fn(){……}
在代码执行之前,把所有的带function关键字的脚本都扫描一遍,然后定义变量;并且同时给变量赋值;
fn
大括号里面的字符串;fn()
时候,这个时候就是函数的运行;函数的运行,会先开辟一个堆内存把字符串当做代码在堆内存中再次运行,函数产生的作用域内还会再进行预解析和代码运行;函数如果多次执行;会产生多个作用域;但是产生的多个作用域里面的内容都是相互独立的;互相没有关系;(在原型和原型链时候再仔细研究原理;)
fn(100,200);//->可以在上面执行,因为预解释的时候声明+定义就已经完成了 function fn(num1, num2) { var total = num1 + num2; console.log(total); }
总结
1、var和function关键字的在预解析的时候操作还是不一样的
2、预解析只发生在当前的作用域下,例如:开始只对window下的进行预解析,只有函数执行的时候才会对函数中的进行预解析;
[重要]刚开始只对window下的进行预解析,fn函数中目前存储的都是字符串,所以var total没啥实际的意义,所以不进行预解析-> “预解析是发生在当前作用域下的”
综合题;
console.log(obj);//->undefined var obj = {name: "xie", age: 25}; function fn(num1, num2) {//代码执行到这一行的时候直接的跳过这一块的代码,因为在预解释的时候我们已经完成了声明加定义 var total = num1 + num2; console.log(total); } var num1 = 12; fn(num1, 100);//执行fn,把全局变量num1的值赋值给形参num1,把100赋值给形参num2
下面是一个预解析思路
var a, b = 0, fn = function () { var a = b = 2; }; fn(); console.log(a, b);
把上面解析成下面就好理解了
var a; window.b = 0; window.fn = function () { //var a = b = 2; var a = 2;//a是私有的和全局没关系 b = 2;//b是全局的 }; fn();//window.fn() console.log(a, b);//undefined 2
console.log(a);//->undefined if (!!("a" in window)) {//"a" in window -> true var a = "xie"; } console.log(a);//->xie
例子中的if是不成立的,预解析的时候,碰到非functon
内的var
,都会声明,无论你写在if else 还是别的判断里; 假设if语句起作用的话,那么第一次log(a)
的时候,就会报错了(没有声明的变量,是不能直接用的,除非typeof
),而声明并且没有赋值的表现才是undefined
;假设不成立; 最开始总结的预解析步骤:代码运行之前,先扫描有没有带var关键字的变量名,有的话,为这个变量名,在内存里开一个空间;预解释是发生在代码执行前的,所以if根本阻挡不了预解析;
匿名函数之函数表达式:把函数定义的部分当做值赋值给一个变量或者元素的事件
fn1();//->undefined() Uncaught TypeError: fn is not a function JS中只有函数可以执行 && JS上面的代码如果报错了,在不进行任何的特殊处理情况下我们下面的代码都不在执行了 var fn1 = function () { console.log("ok"); }; fn1();
//预解释的时候:fn=xxxfff000 fn2();//->"ok" function fn2() { console.log("ok"); } fn2();//->"ok"
预解析的时候:var fn1 = function()... ->fn的默认值是undefined;这里即使有function,也是不能进行预解释的
function fn() { console.log(total); return function sum() {};//return是把函数中的值返回到函数的外面,这里是把function对应的内存地址返回的到函数的外面,例如:return xxxfff111;函数体中return下面的代码都不在执行了 var total = 10; console.log(total); }
匿名函数之自执行函数:定义和执行一起完成了;函数内的声明,只是在函数内使用;
(function(num){ var testStr="test"+num; console.log(num); })(100); console.log(testStr);// testStr is not defined
预解析:
var fn; 声明 fn = xxxfff000; [声明]不用了+定义 fn = xxxfff111; [声明]不用了+定义 // ->fn=xxxfff111 var fn = 12;//window.fn=12 function fn() {//window.fn=function(){} }
JS中作用域只有两种:
ES6可以用let形成块级作用域;https://www.jb51.net/article/67732.htm
// 涉及this的指向和闭包 var num = 20; var obj = { num: 37, fn: (function (num) { this.num *= 3; // window.num * 3 = 60 // num += 15; var num = 45; return function () { this.num *= 4; num += 20; // 调用父作用域的num (45+20) console.log(num); }; })(num), //->把全局变量num的值20赋值给了自执行函数的形参,而不是obj下的30,如果想是obj下的30,我们需要写obj.num }; var fn = obj.fn; fn(); //->65 , 执行了第1次=> window.num = 240 obj.fn(); //->85 闭包(65+20) // 执行了第2次=> obj.num = 37*4 = 148 console.log(window.num, obj.num); // 240,148
以上就是详解JS预解析原理的详细内容,更多关于JS预解析原理的资料请关注其它相关文章!