js的预编译和单线程是什么?

js是单线程的语言,也是一门解析型语言,所以他有着属于自己的一种运行方式,我们所说我预编译就是js解析型语言的一种解释。所以我要先给大家描述一下js的语言分析和同步概念。

1. 语言分析

在我们代码执行的时候,我们的浏览器会先将js所有需要执行的代码全面检测一遍,目的是排除低级的语法错误,检测到错误后,一个一个抛出,而不是一下子全部抛出,所以js是单线程,这也是一种编程上的同步。

什么是js的同步呢?

同步:从上往下按顺序执行的程序; 弊端:中间任何一个程序出现问题,下面代码一个都不会执行就像山间小路,一个不能走了,下面全堵住了

        var a = 10 ;
        var b = 20 ;
        console.log(a)
        console.log(c) // c 没有定义,所以报错,下面的 console.log(b) 就不会执行
        console.log(b)

来我们来看一下运行结果
在这里插入图片描述

什么是js的异步呢?

异步(多个出口):程序的执行顺序是无序的。不会存在等待现象,谁快是先执行
就像高速公路,有多条线,但还是只有一个出口

2. 预编译 (变量提升,函数声明提升 )

在我们学习预编译之前,我先给大家看一个代码:

        console.log(a)

        var a = 10 ;

那么他的输出过结果呢?让我们也来看一下

在这里插入图片描述
那么大家有没有一点奇怪呢?为什么没有报错,我们上面说js是一门解析型语言,按道理来说是解析一行执行一行,那么在我们输出a的时候,a还是没有定义的,所以他应该是会报错的,这里就要说到我们的预编译环节了。
首先我们先来简单的说一下变量提升,它是属于预编译的一种,我先给大家混个眼熟,然后后面再给大家详细讲解。下面我先讲解一下简略版!这个是简略版,大家且先看看:

    将所有变量提升当前作用域最顶端,赋值为undefined
    将函数声明提升到作用域最顶端
    当变量名与函数名重复的时候 , 变量赋值  会将函数本体覆盖 
    
    console.log(a);

    var a = 10 ;
    // 函数声明 
    function a (){

    }
    console.log(a);

那么下面的代码再浏览器的解析中会这样执行:

	//首先将所有变量提升当前作用域最顶端,赋值为undefined
    var a = undefined;

	// 将函数声明提升到作用域最顶端
    function a (){}// 当变量名与函数名重复的时候 , 变量赋值  会将函数本体覆盖 
   
    console.log(a);//所以a的就从一开始的undefined,变成 function a (){}
    
	a = 10;
	
	console.log(a); // 因为值赋是不会有提升效果,所以最后执行赋值 a = 10

在这里插入图片描述.
这样是否就可以解决大家的困惑了呢?
我来总结一下那么就是,①变量声明提升 ②函数声明,如果有重名的就将其覆盖,说到这里我们就可以解决大部分基础性问题了,但是我们讲了就要将其讲的透彻,他为什么会是这样的呢?

下面我就为大家来详细讲解预编译!

预编译存在于函数执行的前一刻!记住了,是函数执行的前一刻,大家先别去想上面的代码,先记住我的这句话,因为上面的代码讲解是存在问题的,仅仅是为了让大家了解一下什么叫做变量提升,函数声明提升 。
首先大家先看一下这四句话:

预编译存在于函数执行的前一刻!
1 生成一个AO 对象
2 将函数体中所有变量声明和形参,作为AO对象的属性名,提升到作用域的最顶端,值为undefined
3 将实参值和形参相统一
4 在函数体中,找函数声明,函数体赋予值(只有函数声明才会提升,表达式不会!!)
function fun(x, y) {
			console.log(a)
			console.log(b)
			console.log(x)
			console.log(y)
			console.log(c)
            var a = 0;
            var b = 0;
            function c() {}
            console.log(a)
			console.log(b)
			console.log(x)
			console.log(y)
			console.log(c)
        }
        fun(1, 2)

我们看到fun()执行,也就是函数执行,那么就再fun执行的前一刻会生成一个AO对象(四句话的第一句)

{
(四句话的第二句)
找函数体中所有变量声明和形参,作为AO对象的属性名,提升到作用域的最顶端,值为undefined ,所以 
var a = undefined;
var b = undefined;
var x = undefined;
var y = undefined;

紧接着(四句话的第三句)
将实参值和形参相统一 ,此时AO对象发生改变
var a = undefined; // 不变
var b = undefined; // 不变
var x = 1;
var y = 2;

最后(四句话的第四句)
在函数体中,找函数声明,函数体赋予值(只有函数声明才会提升,表达式不会!!)
我们找到了 function c() {}
所以AO对象再次变化
var a = undefined; // 不变
var b = undefined; // 不变
var x = 1; // 不变
var y = 2; // 不变
var c = function c() {}
当所有的函数声明找到,并且赋完值,那么我们的预编译的AO对象就执行完毕了
}

所以我们再来观看上面的代码:

function fun(x, y) {
            var a = 0;
            var b = 0;
            function c() {}
        }
        fun(1, 2)
他就会变成:
 function fun(x, y) {
		var a = undefined;
		var b = undefined;
		var x = 1; 
		var y = 2; 
		var c = function c() {}
		// 因为var和函数表达式已经提升了,但赋值没有提升,所以就变成下面这样
		console.log(a) // undefined
		console.log(b) // undefined
		console.log(x) // 1
		console.log(y) // 2
		console.log(c) // function c() {}
		a = 0;
		b = 0;
		console.log(a) // 0
		console.log(b) // 0
		console.log(x) // 1
		console.log(y) // 2
		console.log(c) //function c() {}
        }
        fun(1, 2)

这样就是预编译的结束和代码的执行的过程了,那么我们再来讲一下最上面的代码:

    console.log(a);

    var a = 10 ;
    // 函数声明 
    function a (){

    }
    console.log(a);

大家也可以将其看成一个大的预编译过程也就是GO对象生成的过程流程:
第一步:生成一个GO对象
GO{}
第二步:分析变量:go对象内容
go{a:undefined,}
第三步:分析函声明: go 如下
go(a:function a() {})
因为少了形参所以比上面的AO对象预编译要少一步,所以如果大家仅仅把预编译当成 变量提升,函数声明提升 是明显是不足够的!!
希望大家看了之后有所感悟,并附上一道题,当大伙看完后可以自己去联系一番:

        console.log(a)
        function fun(a, b) {
            console.log(a)
            console.log(b)
            console.log(c)
            var a = 5;
            var bb = function () {
                a++
            }
            if(false){
                var c = 10;
            }
            console.log(a)
            bb()
            console.log(a)
        }
        var a = 100
        fun(10,20)
        console.log(a)
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值