先理解兩個概念:基本型別和參考型別的值
1、基本型別和參考型別的值
(1)定義:
基本型別:指簡單的資料段,比如按值訪問的js五種基本資料型別undefined、null、boolean、number、srtring
參考型別的值:指保存在記憶體中的物件,注意一點,js不允許直接操作物件的空間
(2)相似和區別:
相同:定義兩種型別的方式都類似:創建一個變數并賦值
不同點1:對于參考資料的值,我們可以添加屬性進去,但是基本型別不行,強行添加會報undefined
下面給個例子:
var person = new Object() person.name = "saebr"; console.log(person.name)//saber
而基本型別添加屬性會報undefined:
var name = "saber"; name.sex = "女"; console.log(name.sex)//undefined
不同點2:變數的復制也不相同:
var num = 777; var num1 = num; console.log(num1)//777
基本型別的復制,簡單來說就是用num的值來初始化num1,num1中也保存了值777,但是num和num1保存的777是兩個完全獨立的,
var obj = new Object(); var obj1 = obj; obj.name = "saber"; console.log(obj1.name)//saber
而參考型別的復制,最簡單的話來說就是obj保存了一個物件的新實體,復制的程序就是讓obj1的指標也指向這個物件,因此改變其中一個變數就會影響到另外一個變數,
不同點3:引數傳遞的不同
傳遞基本型別的值時,被傳遞的值會被復制給一個區域變數,而傳遞參考型別的值時,會把值得記憶體的地址復制給區域變數,這么說可能不好理解,擼兩個例子看看:
首先是基本型別的傳遞引數:
function add(num) { num += 1; return num; } var saber = 7; var archer = add(saber); console.log(saber)//7 console.log(archer)//8
使用數值等基本型別來傳參,函式內部的不會影響外部saber的變數,因為num和saber互相不認識,他們僅僅有相同的值,也就是如同上面所說的是完全獨立的,
其次是參考型別的傳遞引數:
var person = new Object(); function setName(obj){ obj.name = "saber" }; setName(person); console.log(person.name)//saber
看上去好像參考型別的傳遞引數是按參考傳遞,第一次看上去好像是這么回事,在區域作用域里面修改物件,會在全域作用域里展現出來,所以誤認為是按參考傳遞,
實際上js都是按值來傳遞引數的,上面的基本型別就不說了,簡單明了,下面寫個例子證明一下,參考型別是按值傳遞的:
var person = new Object(); function setName(obj){ obj.name = "saber" obj = new Object(); obj.name = "archer" }; setName(person); console.log(person.name)//saber
也就是說如果是按參考傳遞的話,person會被修改為指向name屬性值為archer的新物件,但是結果是saber,這已經說明了一切,事實上,當函式執行完畢,這個archer的區域物件會被立即銷毀,
(3)檢測參考型別
檢測基本資料型別使用typeof,那么如何檢測參考型別呢?
所有參考型別的值都是Object的實體,escript提供了instanceof來檢測參考型別和Object建構式,如果是的話,回傳true;
2、作用域
首先,要了解一個概念,全域執行環境被認為是windows物件,然后,每個函式都有自己的執行環境,當執行流進入一個函式時,這個函式的環境就會被推入一個環境堆疊中,當執行完,就會退出這個環境堆疊,然后回傳之前的執行環境
作用域鏈
所以,當代碼在一個環境中執行時,就會創建一個物件的作用域鏈,簡單說一下作用域鏈,作用域鏈的下一個變數物件來自于外部環境,再下一個變數物件又來自更外一層的環境,這樣一層一層直到最外層的全域執行環境windows,
還是擼一串代碼看看,光說根本一連懵逼呀:
var SName = "saber"; function changeSavant(){ var AName = "archer"; // console.log(SName)//saber // console.log(AName)//archer這里可以訪問兩個,訪問不了beateSavant里面的LName beateSavant(); function beateSavant(){ var LName = AName; AName = SName; SName = LName; console.log(SName)//archer console.log(AName)//saber console.log(LName)//archer這里三個都可以訪問到 } } // console.log(SName)//saber這個地方只能訪問到SName // console.log(AName)//AName is not defined changeSavant();
簡單來說,可以看到,函式內部的可以訪問到外部的,但是外部的無法訪問到內部的變數,那么這是如何訪問到的呢,所以這就是作用域鏈的作用,首先函式的區域環境會先在自己的環境中搜索變數和函式名,搜索不到就再搜索上一層的作用域鏈,
這下是不是簡單明了了很多~
延長作用域鏈
js有兩種方式來延長作用域鏈:
(1)try catch中的catch
function add() { try{} catch{}//延長的作用域鏈 }
(2)with
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/178087.html
標籤:JavaScript
上一篇:React/組件
