1. 變數,作用域知多少
ECMAScript的的變數有兩種類型:
基本類型(值類型):簡單數據段
引用類型:多個值構成的對象
在變數賦值結束後,解析器必須知道這個變數時基本數據類型還是引用類型,需要注意的是string在js中是值類型。
復制的差異
值類型的復制會在內存中創建副本,所以彼此間不會影響,但是引用類型只是將變數的引用復制,其指向的仍然是一個對象,會相互影響:
1 var a = {};
2 a.a = 6;
3 var b = a;
4 b.a = 66;
5 alert(a.a);//66
這是一個典型的例子,值類型的就不舉例了。
執行環境與作用域
PS:作用域是面試官的最愛,也是我們經常栽跟頭的地方,這塊我們有必要搞清楚
執行環境(execution)是javascript中非常重要的一個概念。
執行環境定義了變數或者函數有許可權訪問其他數據,決定了他們各自的行為。
每一個執行環境都有一個與之關聯的變數對象(variable object),環境中定義的所有變數和函數都保存到這個對象中,雖然代碼無法訪問,但是解析器會用到他。
在web瀏覽器中window對象便是我們的全局執行環境(最外圍的執行環境,宿主不同便有差異,比如node.js可能就不一樣),因此所有全局變數和函數都是作為window對象的屬性或者方法創建的。
銷毀
某個執行環境中的所有代碼執行完畢,該環境便銷毀,變數對象中的屬性和函數也就完蛋了(閉包會讓情況有所不同)。
函數作用域
每個函數都有自己的「作用域」范圍(執行環境),當執行流進入一個函數時,函數的環境就會進入一個環境棧中,在函數執行完畢後,棧會將其環境彈出,控制權又重新交回之前的環境。ECMAScript程序的執行流就是這個機制在控制。
作用域鏈
當代碼在一個環境中執行時會創建變數對象(variable object),並且該對象擁有一個作用域鏈,作用域鏈的用途是保證對執行環境有許可權訪問的所有變數與函數的有序訪問。
作用域的最前端便是當前執行代碼所在環境的變數對象,若這個變數時函數,就將其活動對象(activation object)作為變數對象,
活動對象最開始只包含一個變數arguments,整個作用域鏈會一直向上延伸直到window,這里上一個經典的例子:
1 var color = 'blue';
2 function changeColor() {
3 var anotherColor = 'red';
4 function swapColor() {
5 var tmpColor = anotherColor;
6 anotherColor = color;
7 color = tmpColor;
8 }
9 swapColor();
10 }
11 changeColor();
以上代碼涉及三個執行環境(execution context):
① 全局環境
② changeColor局部環境
③ swapColor局部環境
全局變數中有一個color和一個函數changeColor
changeColor中有一個anotherColor變數和swapColor函數
swapColor函數中有tmpColor,但是他可以訪問以上所有的變數
2. c語言的執行順序問題(變數的作用域)
程序總是從main函數開始執行的。
對於全局變數,聲明的時候就對其賦值,也就是聲明的時候,初始化它,是可以的。
因為聲明的時候,就初始化,是在編譯的時候,就處理了的。
程序要執行,必須經過編譯和連接兩個步驟,編譯,會掃描整個文件,對每個宏,變數,語句,函數等等,都處理過,改展開的展開,改分配內存的分配內存。
如果某個變數,沒用到,會在連接的時候知道,連接就是要看哪些用到了,哪些沒用到,沒用到的東西,最後不被連接進exe文件中。
int a=2,b=4; 這個語句,並不是給全局變數賦值的語句,而是聲明的同時賦值的
你不能這樣寫:
int a,b;
a=2;//這才是賦值,如果放到所有函數的外面,是不行的。
int first_fun(){
b=4;//放在函數內部,是可以的
}
外部程序塊的變數的作用域,也是向下兼容的。
因此,為例first_fun()中就不能用到C這個變數。就如:
int last_fun()
{
int a, b;
c= a;////////a,b,c都是局部變數,但c在下面才定義,所以,這里不能使用
int c;
}
3. 請問怎麼樣修改電腦 環境變數的前後順序
java version 1.7.0_03 JavaTM SE Runtime Environment build 1.7.0_03-b05 Java HotSpotTM 64-Bit Server VM build 22.1-b02 mixed mode JAVA變數path classpth java_home設置 我在win7安裝的版本是jdk-7u3-windows-x64 最新版本的下載地址是http://www.oracle.com/technetwork/java/javase/downloads/index.html 如果是壓縮包解壓那就得到exe文件點擊安裝即可中間過程需要選擇接受一些要求以及配置一些工具一切全選就是按照默認不要動就行不過安裝目錄是你隨便定的只要你能記得住。。。 默認安裝在C:Program FilesJavajdk1.7.0_03目錄下 然後滑鼠右鍵單擊計算機-〉屬性-〉高級選項-〉系統設置——最右下角有一個「環境變數」。以後的操作就在下邊的一個「系統變數」進行操作。 我們將要對環境變數配置為 PATH.JAVA_HOMEbin等同於C:Program FilesJavajdk1.7.0_03bin CLASSPATH.JAVA_HOMElibdt.jarJAVA_HOMElibtoos.jar JAVA_HOMEC:Program FilesJavajdk1.7.0_03 在新的打開界面中的系統變數需要設置三個屬性「JAVA_HOME」、「CLASSPATH」、「Path」。 1.看一下你的機器裡面是否已經有了JAVA_HOME這個系統變數正常情況下只要沒有裝過jdk是不會有的點「新建」然後在變數名寫上JAVA_HOME然後在變數值寫入剛才安裝的路徑「C:Program FilesJavajdk1.7.0_03」。點擊確定保存。 2.其次在系統變數裡面找到Path沒有就新建然後點編輯path變數的含義就是系統在任何路徑下都 可以識別java命令則變數值為「.JAVA_HOMEbin」也可以直接寫上「C:Program FilesJavajdk1.7.0_03bin」 。點擊確定保存。 3. 最後再點「新建」然後在變數名上寫CLASSPATH該變數的含義是為java載入類class or lib路徑只有類在CLASSPATH中java命令才能識別。其值為:「.JAVA_HOMElibdt.jarJAVA_HOMElibtoos.jar 要加.表示當前路徑」。 以上三個變數設置完畢則按「確定」直至屬性窗口消失下來是驗證看看安裝是否成功。先打開「開始 」- 「運行」打入「cmd」進入dos系統界面。然後打「java -version」如果安裝成功。系統會顯 示java version 1.7.0_03 安裝成功了
4. 在LINUX中,環境變數的載入順序
內核啟動的時候,各個驅動初始化的工作在文件init/main.c中的do_basic_setup()函數中做.
------------------------------------------------------------------------------------------------------
static void __init do_basic_setup(void)
{
/* drivers will send hotplug events */
init_workqueues();
usermodehelper_init();
driver_init();
#ifdef CONFIG_SYSCTL
sysctl_init();
#endif
/* Networking initialization needs a process context */
sock_init();
do_initcalls();
}
------------------------------------------------------------------------------------------------------
其中的driver_init()做一些核心的初始化,看看代碼就明白了.
相應的驅動程序的初始化在do_initcalls()中做.
------------------------------------------------------------------------------------------------------
static void __init do_initcalls(void)
{
initcall_t *call;
int count = preempt_count();
for (call = __initcall_start; call < __initcall_end; call++) {
char *msg;
if (initcall_debug) {
printk(KERN_DEBUG "Calling initcall 0x%p", *call);
print_fn_descriptor_symbol(": %s()", (unsigned long) *call);
printk("\n");
}
(*call)();
msg = NULL;
if (preempt_count() != count) {
msg = "preemption imbalance";
preempt_count() = count;
}
if (irqs_disabled()) {
msg = "disabled interrupts";
local_irq_enable();
}
if (msg) {
printk(KERN_WARNING "error in initcall at 0x%p: "
"returned with %s\n", *call, msg);
}
}
/* Make sure there is no pending stuff from the initcall sequence */
flush_scheled_work();
}
------------------------------------------------------------------------------------------------------
這個__initcall_start是在文件 arch/xxx/kernel/vmlinux.lds.S (其中的xxx 是你的體系結構的名稱,例如i386)
這個文件是內核ld的時候使用的.其中定義了各個sectioin,看看就明白了。
在這個文件中有個.initcall.init, 代碼如下:
------------------------------------------------------------------------------------------------------
__initcall_start = .;
.initcall.init : {
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
}
------------------------------------------------------------------------------------------------------
這里有7個初始化的優先順序,內核會按照這個優先順序的順序依次載入.
這些優先順序是在文件include/linux/init.h 中定義的. 你注意一下宏 __define_initcall的實現就明白了.
相關代碼如下:
#define __define_initcall(level,fn) \
static initcall_t __initcall_##fn __attribute_used__ \
__attribute__((__section__(".initcall" level ".init"))) = fn
#define core_initcall(fn) __define_initcall("1",fn)
#define postcore_initcall(fn) __define_initcall("2",fn)
#define arch_initcall(fn) __define_initcall("3",fn)
#define subsys_initcall(fn) __define_initcall("4",fn)
#define fs_initcall(fn) __define_initcall("5",fn)
#define device_initcall(fn) __define_initcall("6",fn)
#define late_initcall(fn) __define_initcall("7",fn)
我們可以看到,我們經常寫的設備驅動程序中常用的mole_init其實就是對應了優先順序6:
#define __initcall(fn) device_initcall(fn)
#define mole_init(x) __initcall(x);
文章出處:http://www.diybl.com/course/6_system/linux/Linuxjs/2008628/128990.html
5. javascript 中不同類型以及不同環境下變數的內存都是何時釋放
一.基本類型和引用類型的值
javascript中的變數包含兩種不同數據類型的:基本類型值和引用類型值。基本類型值指的是簡單的數據段,而引用類型值指那些可能右多個值構成的對象。
1.動態的屬性
定義基本類型值和引用類型值的方式是類似的:創建一個變數並為該變數賦值。但是,當這個值保存到變數中以後,對不同類型值可以執行的操作則大相徑庭。
對於引用類型的值,我們可以為其添加屬性和方法,也可以改變和刪除其屬性和方法:
var person = new Object();
person.name = "Nicholas";
alert(person.name);// 「Nicholas」
基本類型值不能動態添加:
var name = "Nicholas";
name.age = 27;
alert(name.age);// undefined
2.復制變數值
復制變數值時兩種類型也會有所不同。
基本類型:
重新在內存中開辟一段空間,賦值前後的兩者相互獨立
引用類型:
雖然也會重新開辟一段空間,但其接受到的值實際上是一個指針,而這個指針指向存儲在堆中的一個對象。賦值操作結束後,兩個變數實際上將引用同一個對象。
3.傳遞參數
javascript中所有函數的參數都是按值傳遞的。基本類型值的傳遞如同基本類型變數的復制一樣,而引用類型的值的傳遞,則如同引用類型變數的復制一樣。
在向參數傳遞引用類型的值時,會把這個值在內存中的地址復制給一個局部變數,因此這個局部變數的變化會反映在函數的外部,情況下面例子:
function addTen(num){
num += 10;
return num;
}
var count = 20;
var result = addTen(count);
alert(count);// 20,沒有變化
alert(result);// 30
引用傳遞:
function setName(obj){
obj.name = "Nicholas";
}
var person = new Object();
setName(person);
alert(person.name);// "Nicholas"
證明對象是按值傳遞的例子:
function setName(obj){
obj.name = "Nicholas";
obj = new Object();
obj.name = "Greg";
}
var person = new Object();
setName(person);
alert(person.name);// "Nicholas"
4.檢測類型
在檢測基本類型時typeof是非常得力的助手,但在檢測引用類型的值時,這個操作符的用處不大。通常,我們並不是想知道某個值是對象,而是想知道它是什麼類型的對象。為此,javascript提供了instanceof操作符,其語法如下:
result = variable instanceof constructor
alert(person instanceof Object);// 變數person是Object嗎?
alert(colors instanceof Array);// 變數colors是Array嗎?
alert(pattern instanceof RegExp);// 變數parrern是RegExp嗎
二.執行環境和作用域
執行環境是javascript中最為重要的一個概念。執行環境定義了變數或函數有權訪問的其他數據,決定了它們各自的行為。每個執行環境都有一個與之關聯的變數對象,環境中定義的所有變數和函數都保存在這個對象中。
每個函數都有自己的執行環境。當執行流進入一個函數時,函數的執行環境就會被推入一個環境棧中。而在函數執行之後,棧將其環境彈出,把控制權返回給之前的執行環境。Javascript中的執行流正式右這個方便的機制控制著。
當代碼在一個環境中執行時,會創建變數對象的一個作用域鏈。作用域鏈的用途是保證對執行環境有權訪問的所有變數和函數的有序訪問。作用域鏈的前端,始終都是當前執行的代碼所在環境的變數對象。如果這個環境是函數,則將其活動對象作為變數對象。活動對象最開始只包含一個變數,即arguments對象。作用域鏈中的下一個變數對象來自包含(外部)環境,直至全局執行環境的變數對象
1.延長作用域鏈
雖然執行環境的類型總共只有兩種——全局和局部(函數),但是可以延長作用域鏈。因為有些語句可以在作用域鏈的前端臨時增加一個變數對象,該變數對象在執行代碼後被移除:
try-catch語句的catch快
with語句
2.沒有塊級作用域
先看如下例子:
if (true){
var color = "blue";
}
alert(color);// "blue"
for (var i = 0; i < 10; ++i){
doSomething(i);
}
alert(i); // 10
使用var聲明的變數會自動被添加到最接近的環境中。在函數內部,最接近的環境就是函數的局部環境;在with語句中,最接近的環境是函數環境。如果初始化變數時沒有使用var聲明,該變數會被添加到全局變數
3.垃圾收集
1.收集方式
標記清除、引用清除
2.性能問題(臨界值)
3.管理內存(不用的數據即使設置為null)
四.總結
javascript變數可以用來保存兩種類型的值:基本類型值和引用類型值。基本類型的值源自以下5種基本類型數據:Undefined、Null、Boolean、Number和String。基本類型值和引用類型值具有以下特點:
基本類型值在內存中占據固定大小的空間,因此被保存在棧內存中
從一個變數向另一個變數復制基本類型的值,會創建這個值的一個副本
引用類型的值是對象,保存在堆內存中
包含引用類型值的變數實際上包含的並不是對象本身,而是一個指向該對象的指針
從一個變數向另一個變數復制引用類型的值,賦值的其實是指針,因此兩個變數最終都指向同一個對象
確定一個值是哪種基本類型可以使用typeof操作符,而確定一個值是哪種引用類型可以使用instanceof操作符
所有變數(包括基本類型和引用類型)都存在於一個執行環境(也稱為作用域)當中,這個執行環境決定了變數的聲明周期,以及哪一部分代碼可以訪問其中的變數。以下是關於執行環境的幾點總結:
執行環境有全局執行環境(也成為全局環境)和函數執行環境之分
每次進入一個新執行環境,都會創建一個用於搜索變數和函數的作用域鏈
函數的局部環境不僅有權訪問函數作用域中的變數,而且有權訪問其包含(父)環境,乃至全局環境
全局環境只能訪問在全景環境中定義的變數和函數,而不能直接訪問局部環境中的任何數據
變數的執行環境有助於確定應該合適釋放環境
javascript是一門具有自動垃圾收集機制的編程語言,開發人員不必關心內存分配和回收問題。可以對Javascript的垃圾收集常式作如下總結:
離開作用域的值將被自動標記為可以回收,因此將在垃圾收集期間被刪除
「標記清除」是目前主流的垃圾收集演算法,這種演算法的思想是給當前不實用的值加上標記,然後再回收其內存
另一種垃圾收集演算法是「引用計數「,這種演算法的思想是跟蹤記錄所有值被引用的次數。Javascript引擎不淺不再使用這種演算法;但在IE中訪問非原聲JavaScript對象(如DOM對象)時,這種演算法仍然可能導致問題
當代碼中存在循環引用現象時,「引用技術」演算法就會導致問題
解除變數的引用不僅有助於消除循環引用現象,而且對垃圾收集也有好處。為了確保有效地回收內存,應該及時接觸不再使用的全局對象、全局對象屬性以及循環引用變數的引用
6. 環境變數PATH, CLASSPATH的作用,以及它們的設置方法
我們發現每次程序編譯與運行都要輸入D:\develop\Java\jdk1.7.0_72\bin後,才能使用javac.exe與java.exe,這樣的方式很麻煩,那麼,能否不輸入D:\develop\Java\jdk1.7.0_72\bin呢?是可以的,通過配置Windows的PATH環境變數來完成。
PATH變數中保存著多個路徑,當我們在DOS控制台中使用的程序只給出程序名稱,而沒有給出完整路徑時,那麼Windows系統會到PATH變數保存的路徑中去查找程序。我們如果把「D:\develop\Java\jdk1.7.0_72\bin」路徑保存到PATH變數中,那麼在我們使用javac或java時,Windows系統就會自動到「D:\develop\Java\jdk1.7.0_72\bin」路徑下查找javac和java了。
l
配置步驟:
滑鼠右鍵點擊計算機
→
屬性
→
高級系統設置
→
點擊環境變數
→
找到系統變數中的PATH
→
點擊編輯按鈕。
將JDK安裝目錄\bin路徑(我的電腦上的D:\develop\Java\jdk1.7.0_72\bin)配置到PATH變數中,用英文分號與其他變數隔開。
注意:配置PATH後文件的訪問順序:先訪問當前路徑,如果當前路徑沒有該文件,則再訪問PATH配置的路徑。
除了直接配置path的方式外,針對Java還可以使用第二種JAVA_HOME的方式進行配置:
l
右鍵點擊計算機
→
選擇屬性
→
更改設置
→
點擊高級
→
點擊環境變數
→
在系統環境變數中,創建名為JAVA_HOME的環境變數
→
將java所在的目錄路徑配置到JAVA_HOME變數中,用;與其他變數分隔
→
在path環境變數中添加%JAVA_HOME%\bin
7. 為什麼要配置環境變數以及配置環境變數的步驟
1、計算機在執行命令的時候是在環境變數找對應的命令的位置的。如果不正確設置環境變數就不能正確使用相應的命令
2、比如說要執行
java
命令,如果不設置環境變數path包括你的jdk安裝路徑,那系統去哪找java.exe文件。
如果執行某個命令,系統無法在當前文件夾里找到對應的.exe,那麼系統就會去path包含的路徑找挨個找看是否能知道對應的.exe,一旦找到第一個對應的.exe就運行命令,其他的路徑下就不找了。如果找不到就會報「系統找不到某某命令」的提示。
其他的環境變數也一樣的用途,只不過是用來存儲一些信息用的,這些信息可以被系統使用,也可以被應用程序使用
配置環境變數步驟:
方式一:此電腦--》屬性--》左上側的高級系統設置--》高級---》環境變數
方式二:點擊系統左下角的搜索--》輸入"環境"兩個字--》"編輯系統環境變數"
8. 在windows系統命令行環境中如何訪問變數值
用百分號將變數名括起來:
如:
cd %windir%