预解释1. JS基础知识1.1 先介绍js的基本数据类型基本数据类型 — 值操作有number、string、boolean、null、undefined引用数据类型 —- 引用地址object、array、Date1.2 执行环境当浏览器加载HTML页面的时候,首先会提供一个供全局JS代码执行的环境 — 全局作用域(global/window)如下代码是在script中var num = 12;var obj = { name:“houdashuaige”, age:18 };function fn() { console.log(“好好学习 天天向上”);}console.log(fn) //把整个函数定义的部分(函数本身)在控制台输出console.log(fn()) //输出当前函数的执行返回结果fn()//return 后面是啥 返回啥 如果没有return 返回undefined示意图如下如果执行obj.age = 20;首先通过地址xxxfff000 找到对应的空间 然后把空间中age属性对应的属性值修改为20;其中fn存储的是一个地址 代表的时当前函数的整体2. 预解释2.1 预解释的基本概念在当前的作用域中,JS代码执行之前,浏览器首先会默认地把所有带var、function的进行提前的声明或者定义2.1.1 理解声明(declare)和定义(defined)var num = 12;声明: var num; //告诉浏览器在全局作用域中有一个num的变量定义: num = 12(发生在代码执行过程中 不在预解释中); //给变量进行赋值function fn() { console.log(“this is a test”);}函数预解释fn = xxxfff000; 声明: fn //告诉浏览器在全局作用域中有一个fn的函数定义: fn = xxxfff000; //给fn赋值 指向函数的地址注释: 所以对于带var 和 function关键字的在预解释的时候操作还是不一样的var: 对于带var的变量 预解释只会声明 不会进行定义****function: 在预解释的时候声明+定义 一起完成了附代码//函数只有在执行的时候才会对函数内部的代码进行预解释console.log(num);// undefined 提前声明 但未定义 默认undefinedvar num = 12;console.log(num);// 12var obj = { name: “hou”, age: 7 };fn(100,200);//代码可以在这执行 因为预解释的时候 声明+名义就已经完成了function fn(num1,num2) { var total = num1 + num2; console.log(total);}附示意图2.1.2 函数预解释(代码内部)function fn(num1,num2) { var total = num1 + num2; console.log(total);}附示意图2.1.3 JS中内存的分类(预解释发生在栈内存)//栈内存:用来提供一个供JS代码执行的环境 —>作用域(全局作用域/私有作用域)//堆内存:用来存储引用数据类型的值 —>对象存储的时属性名和属性值//函数存储的是代码字符串2.1.4 如何区分私有变量和全局变量(主要用来分析函数预解释)注释: 下述都是为了更好地理解"函数预解释",请耐心阅读"全局作用域"下声明(预解释的时候)的变量是全局变量在"私有作用域"中声明的变量和"函数的形参"都是私有的变量在私有作用域中,我们代码执行的时候遇到了一个变量,首先我们要确认它是否是私有的变量,如果是私有的变量,那么和外面的变量没有任何的关系,如果不是私有的,则往当前作用域的上级作用域查找,如果上级作用域没有则继续查找,一直找到window为止 —>(“作用域链”)当函数执行的时候(直接目的:让函数体中的代码执行),首先会形成一个新的私有作用域,然后按照如下步骤执行🅰️如果有形参,先给形参赋值b:进行私有作用域中的预解释c:私有作用域中的代码从上到下执行函数形成一个新的私有作用域保护了里面的私有变量不受外界的影响(外面修改不了私有的,私有的也修改不了外面的)形成了"闭包" —>(保护机制)2.1.5 全局作用域中,带var和不带var的区别区别1: 带var的可以进行预解释,所以在赋值的前面执行不会报错,不带var的是不能进行预解释的,在前面执行会报错代码如下console.log(num);—>undefinedvar num = 12;console.log(num2); —>直接报错 因为num2没有预解释num2=13;区别2: 看下述代码var num = 12;console.log(num);//12num2 = 12;console.log(num2) //12 —>相当于window.num2//关系:num2 = 12 —>相当于给window增加了一个叫num2的属性名,属性值是12//var num =12 —>相当于给全局作用域增加了一个全局变量num,但是不仅如此,//它也相当于给window增加了一个属性名num,属性值是12函数内部不带var的代码如下var total = 0;function fn() { console.log(total) // 0 total = 100;//相当于修改了全局变量total}fn();console.log(total)//—>100//注释:私有作用域中出现的一个变量不是私有的,则往上级作用域查找,上级没有则继续向上查找,一直找到window//如果window下没有 分两种情况://1、如果是获取值:console.log(total) –>直接报错//2、如果是设置值:total = 100;—>相当于给window加了total属性//3、JS中如果在不进行任何特殊处理的情况下,上边的代码报错,下边的代码都不执行了2.1.6 预解释是一种毫无节操的机制预解释的时候不管你的条件是否成立,都要把带var的进行提前声明具体代码如下if(!(“num” in window)) { //===>if(false) var num = 12;}console.log(num);//—>实际输出undefined//分析:不管if的条件是否成立 都会把带var的进行预解释 (var num = 12)//所以"num" in window 是true !(“num” in window) —>false //if条件是false var num = 12 不会执行 所以 console.log(num) 是undefined匿名函数之函数表达式把函数定义的部分当作一个值赋给我们的变量/或者赋给元素的某一个事件fn();//====>fn 是undefined 相当于 undefined() 报错 uncaught TypeError: fn is not a function//window下的预解释 var fn; 预解释的时候只会预解释 “="(等号)左边的//右边的是值 不参与预解释var fn = function() { console.log(“ok”);}自执行函数定义和执行一起完成的//自执行函数定义的那个function在全局作用域下不进行预解释,当代码执行到这个位置的时候,定义和执行一起完成了//自执行函数的5种形式(function(num){})(100);//常用形式~function(){}(100);+function(){}(100);-function(){}(100);!function(){}(100)函数内部return相关function fn() { console.log(num);//—>undefined return function() {}; var num = 100;}fn();//函数体种return 下面的代码虽然不再执行了,但是需要进行预解释//return 后边跟着的是我们的返回值,所以不进行预解释预解释经典习题解析//注释:在预解释的时候,如果名字已经声明过了,不需要重新声明,但是需要重新定义(赋值)//JS比较懒,声明过一次,便不再声明,但是可以重新定义//在JS中,如果变量的名字和函数的名字重复了,也算冲突fn();function fn() {console.log(1)};fn();var fn = 10;fn();function fn() {console.log(2)};fn();//输出结果是2 、2 、 报错:fn is not a function 后边代码不执行附解释图(自己画预解释图 学习 分析会更快 更有效)
JS预解释
December 20, 2018 · 2 min · jiezi