欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解JS預解析原理

 更新時間:2020年06月16日 11:11:34   作者:Mikejiawei  
這篇文章主要介紹了JS預解析原理的相關知識,文中講解非常細致,代碼幫助大家更好的理解和學習,感興趣的朋友可以了解下

預解析的的不同機制

預解析也叫預聲明,是提前解析聲明的意思;預解析是針對變量和函數(shù)來說的;但是變量和function的的預解析是兩套不同的機制;

  • 當瀏覽器加載我們的HTML頁面的時候,首先會提供一個供JS代碼執(zhí)行的環(huán)境->全局作用域global(瀏覽器中的全局作用域,也叫頂級作用域是window)
  • JS中的內(nèi)存空間分為兩種:棧內(nèi)存、堆內(nèi)存
  1. 棧內(nèi)存;提供JS代碼執(zhí)行的環(huán)境,存儲基本數(shù)據(jù)類型的值;->全局作用域或者私有的作用域其實都是棧內(nèi)存;
  2. 堆內(nèi)存;存儲引用數(shù)據(jù)類型的值(對象是把屬性名和屬性值儲存進去,函數(shù)是把函數(shù)體內(nèi)的代碼當做字符串儲存進去)
  • 在當前的作用域中,JS代碼執(zhí)行之前,瀏覽器首先會默認的把所有代var和function的進行提前的聲明或者定義,->“預解析”(也叫變量提升)

var的預解析機制

var a=1

  • 1、代碼運行之前,先掃描有沒有帶var關鍵字的變量名,有的話,為這個變量名在內(nèi)存里開一個空間;這時候變量名a是不代表任何值的;用undefined來表示;undefined是一個標識符/記號,表示找不到這個變量名所代表的數(shù)據(jù);不存在的意思;這個階段叫變量的聲明;
  • 2、當代碼運行的時候,則給數(shù)據(jù)1開辟一個內(nèi)存空間;
  • 3、讓數(shù)據(jù)1和變量名a綁定在一起;變量類型指的就是數(shù)據(jù)類型;按照js語言的原理來說變量類型有undefined類型;但是數(shù)據(jù)類型是沒有undefined這種數(shù)據(jù)類型的;只有”undecided”這種字符串類型(字符串類型是數(shù)據(jù)類型的一種);同理也沒有unll這個數(shù)據(jù)類型,但是有”null”這種字符串類型;
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 關鍵字的預解析步驟

function fn(){……}

在代碼執(zhí)行之前,把所有的帶function關鍵字的腳本都掃描一遍,然后定義變量;并且同時給變量賦值;

  • 1、函數(shù)的定義只是保存一些字符串;預解析的時候在內(nèi)存里保存fn大括號里面的字符串;
  • 2、代碼運行時候,讀到fn()時候,這個時候就是函數(shù)的運行;函數(shù)的運行,會先開辟一個堆內(nèi)存把字符串當做代碼在堆內(nèi)存中再次運行,函數(shù)產(chǎn)生的作用域內(nèi)還會再進行預解析和代碼運行;

函數(shù)如果多次執(zhí)行;會產(chǎn)生多個作用域;但是產(chǎn)生的多個作用域里面的內(nèi)容都是相互獨立的;互相沒有關系;(在原型和原型鏈時候再仔細研究原理;)

fn(100,200);//->可以在上面執(zhí)行,因為預解釋的時候聲明+定義就已經(jīng)完成了 
function fn(num1, num2) { 
	var total = num1 + num2; 
	console.log(total);
}

總結(jié)

1、var和function關鍵字的在預解析的時候操作還是不一樣的

  • var -> 在預解析的時候只是提前的聲明了這個變量,只有當代碼執(zhí)行的時候才會完成賦值操作
  • function -> 在預解析的時候會提前的把聲明加定義都完成了(在代碼執(zhí)行的時候遇到定義的代碼直接的跳過)

2、預解析只發(fā)生在當前的作用域下,例如:開始只對window下的進行預解析,只有函數(shù)執(zhí)行的時候才會對函數(shù)中的進行預解析;

[重要]剛開始只對window下的進行預解析,fn函數(shù)中目前存儲的都是字符串,所以var total沒啥實際的意義,所以不進行預解析-> “預解析是發(fā)生在當前作用域下的”

綜合題;

	console.log(obj);//->undefined
	var obj = {name: "xie", age: 25};
 function fn(num1, num2) {//代碼執(zhí)行到這一行的時候直接的跳過這一塊的代碼,因為在預解釋的時候我們已經(jīng)完成了聲明加定義
 var total = num1 + num2;
 console.log(total);
 }
 var num1 = 12;
 fn(num1, 100);//執(zhí)行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

預解析機制

  • 1、不管條件是否成立都要進行預解析
console.log(a);//->undefined
if (!!("a" in window)) {//"a" in window -> true
 var a = "xie";
}
console.log(a);//->xie

例子中的if是不成立的,預解析的時候,碰到非functon內(nèi)的var,都會聲明,無論你寫在if else 還是別的判斷里; 假設if語句起作用的話,那么第一次log(a)的時候,就會報錯了(沒有聲明的變量,是不能直接用的,除非typeof ),而聲明并且沒有賦值的表現(xiàn)才是undefined;假設不成立; 最開始總結(jié)的預解析步驟:代碼運行之前,先掃描有沒有帶var關鍵字的變量名,有的話,為這個變量名,在內(nèi)存里開一個空間;預解釋是發(fā)生在代碼執(zhí)行前的,所以if根本阻擋不了預解析;

  • 2、預解析只發(fā)生在”=“的左邊,只把左邊的進行預解析,右邊的是值是不進行預解析的

匿名函數(shù)之函數(shù)表達式:把函數(shù)定義的部分當做值賦值給一個變量或者元素的事件

fn1();//->undefined() Uncaught TypeError: fn is not a function JS中只有函數(shù)可以執(zhí)行 && JS上面的代碼如果報錯了,在不進行任何的特殊處理情況下我們下面的代碼都不在執(zhí)行了
var fn1 = function () {
 console.log("ok");
};
fn1();
//預解釋的時候:fn=xxxfff000
fn2();//->"ok"
function fn2() {
 console.log("ok");
}
fn2();//->"ok"

預解析的時候:var fn1 = function()... ->fn的默認值是undefined;這里即使有function,也是不能進行預解釋的

  • 3、函數(shù)體中return下面的代碼都不在執(zhí)行了,但是下面的代碼需要參加預解析;而return后面的東西是需要處理的,但是由于它是當做一個值返回的,所以不進行預解析;
function fn() {
 console.log(total);
 return function sum() {};//return是把函數(shù)中的值返回到函數(shù)的外面,這里是把function對應的內(nèi)存地址返回的到函數(shù)的外面,例如:return xxxfff111;函數(shù)體中return下面的代碼都不在執(zhí)行了
 var total = 10;
 console.log(total);
}
  • 4、匿名函數(shù)的function在全局作用域下是不進行預解析的;

匿名函數(shù)之自執(zhí)行函數(shù):定義和執(zhí)行一起完成了;函數(shù)內(nèi)的聲明,只是在函數(shù)內(nèi)使用;

 (function(num){
 var testStr="test"+num;
 console.log(num);
})(100);

console.log(testStr);// testStr is not defined
  • 5、在預解析的時候,如果遇到名字重復了,只聲明一次。 不重復的聲明,但是賦值還是要重復的進行的

  預解析:

 var fn; 聲明
 fn = xxxfff000; [聲明]不用了+定義
 fn = xxxfff111; [聲明]不用了+定義
 // ->fn=xxxfff111
 var fn = 12;//window.fn=12
 function fn() {//window.fn=function(){}
 }

  JS中作用域只有兩種:

  • window全局作用域;
  • 函數(shù)執(zhí)行形成的私有作用域;
  • {name:“”} if(){} for(){} while(){} switch(){} 這些都不會產(chǎn)生作用域;

ES6可以用let形成塊級作用域;http://www.dbjr.com.cn/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; // 調(diào)用父作用域的num (45+20)
			console.log(num);
		};
	})(num), //->把全局變量num的值20賦值給了自執(zhí)行函數(shù)的形參,而不是obj下的30,如果想是obj下的30,我們需要寫obj.num
};
var fn = obj.fn; 
fn(); //->65 , 執(zhí)行了第1次=> window.num = 240
obj.fn(); //->85 閉包(65+20) // 執(zhí)行了第2次=> obj.num = 37*4 = 148
console.log(window.num, obj.num); // 240,148

以上就是詳解JS預解析原理的詳細內(nèi)容,更多關于JS預解析原理的資料請關注腳本之家其它相關文章!

相關文章

最新評論