js笔记(一)js基础、程序结构、函数
| 一、js 基礎 | 1. javascript的組成; 2. 運行js; 3. 打印信息; 4. 關鍵字var; 5. js中的數據類型; 6. NaN(not a number); 7. js運算符; 8. 數據類型轉換; 9. 解決精度缺失問題; 10. 進制的轉換; 11. undefined 和 not a defined |
| 二、程序的結構-單雙分支 | 2.1 分支結構 1. 單分支;2. 雙分支;3. 多分支; 2.2 循環結構 1. 循環三要素;2. 循環語句;3. do-while和while的區別;4. 死循環;5. 循環中的關鍵字 |
| 三、函數 | 1. 函數的使用; 2. 函數的分類; 3. 函數的參數; 4. arguments; 5. return; 6. 作用域; 7. 變量提升; 8. 遞歸 |
一、js 基礎
網頁的組成:
(1)結構:html
(2)樣式:css
(3)行為:JavaScript
1. JavaScript(簡稱“js”)的組成:
(1)DOM: 文檔對象模型,操作 html(在 js 中叫 DOM),網頁結構;
(2)BOM: 瀏覽器對象模型,js 要運行在瀏覽器中,意味著 js 不僅要遵循自己的規則,還要遵循瀏覽器的規則(即BOM),提供了操作瀏覽器的方法;
(3)ECMAScript: 語法規范,規定了 js 怎么寫,寫什么;
2. 運行 js
js 也是一種腳本語言,有兩種方式在HTML頁面進行引入。
(1)外聯 js: <script src="相對路徑"></script>
(2)內部 js: <script type="text/javascript">//...</script>
3. 打印信息
跟編程沒有任何關系,用來觀察數據處理的結果,用來測試,用來調bug。
(1)向 頁面 打印信息:document.write(); ? ? ? 操作的是 DOM,影響頁面(坑: 頁面正在加載時執行 docment.write(),頁面正常;頁面加載完執行docment.write(),頁面被覆蓋);
(2)向 控制臺 打印信息:console.log(); ? ? ? 操作的是 瀏覽器,既不影響頁面,也不影響操作;
(3)向 瀏覽器彈出框 打印信息:alert();? ? ? 操作的是 BOM,需要手動關閉;
4. 關鍵字 var
(1)原理: 我們所寫的程序運行在內存中,當我們使用關鍵字 var 聲明一個變量時,計算機會從內存中分一個空間,為我們存放 不同類型 的內容做準備。
(2)變量命名規則:
- 只能以 字母、_ 、$ 開頭;
- 盡量使用數據類型做前綴;
- 不允許使用 關鍵字 和 保留字;
5. js 中的數據類型
(1)字符型(String): 所有用引號引起來的數據 “” 和 ‘’ ;
(2)數值型(Number): 0123456789;
(3)布爾型(Boolean): true 和 false;
(4)undefined: undefined;
(5)對象型(object): {} 就是對象;
(6)數值(arr): [] 就是數值
-
檢測數據類型的方法:
console.log("基礎數據類型");console.log(typeof ""); //stringconsole.log(typeof 1); //numberconsole.log(typeof true); //booleanconsole.log(typeof undefined); //undefinedconsole.log(typeof null); //objectconsole.log(typeof []); //objectconsole.log(typeof {}); //objectconsole.log("引用數據類型");console.log(typeof function(){}); //functionconsole.log(typeof new Function()); // functionconsole.log(typeof new Date()); //object console.log(typeof new RegExp()); //object
(1)typeof :用來檢測數據類型;
typeof 返回七種可能的值:“number”、“string”、“boolean”、“object”、“symbol”、“function”和“undefined”。- ① 對于基本類型,除 null 以外,均可以返回正確的結果。
- ② 對于 null ,返回 object 類型。
- ③ 對于引用類型,除 function 以外,一律返回 object 類型。
- ④ 對于 function 返回 function 類型。
其中,null 有屬于自己的數據類型 Null , 引用類型中的 數組、日期、正則 也都有屬于自己的具體類型,而 typeof 對于這些類型的處理,只返回了處于其原型鏈最頂端的 Object 類型,沒有錯,但不是我們想要的結果。
(2)instanceof,具體參考
instanceof 是用來判斷 A 是否為 B 的實例,表達式為:A instanceof B,如果 A 是 B 的實例,則返回 true,否則返回 false。 在這里需要特別注意的是:instanceof 檢測的是原型。
(3)constructor,具體參考
(這里依然拋開null和undefined)乍一看,constructor似乎完全可以應對基本數據類型和引用數據類型,都能檢測出數據類型,事實上并不是如此:聲明了一個構造函數,并且把他的原型指向了Array的原型,所以這種情況下,constructor也顯得力不從心了
(4)Object.prototype.toString.call()
jQuery源碼就是采用這種方法檢測的。
var a = Object.prototype.toString; console.log(a.call("aaa")); //[object String] console.log(a.call(1)); //[object Number] console.log(a.call(true)); //[object Boolean] console.log(a.call(null)); //[object Null] console.log(a.call(undefined)); //[object Undefined] console.log(a.call([])); //[object Array] console.log(a.call(function() {})); //[object Function] console.log(a.call({})); //[object Object] console.log(a.call(new Date())); //[object Date] console.log(a.call(new RegExp())); //[object RegExp]
6. NaN(not a number)
(1) 不是一個數字的數值型數據,非法的運算 會得到 NaN;
(2)NaN 不等于 NaN;
(3)isNaN()是不是一個數字;檢測 NaN;
得到 NaN 時,返回 true,如果是數字,返回 false。
7. js 運算符:
(1)算術運算符:
- -、*、/、%,會把兩邊的數據,當成數值進行運算;
- 而 + 號兩邊只要出現一個字符,那么就不是加法了,而是字符串的拼接;
(2)關系運算符:
- 只要關系運算符兩邊,存在數值,會把兩邊的數據,當成數值進行運算;
- 兩邊都是字符,會按照字符的比較規則,比較(逐位比較);
- === 除了比較值,還比較了類型,不存在類型轉換;console.log(1 == true); //true console.log(1 === true); //false
(3)邏輯運算符:||、&&、!;
(4)賦值運算符 = += -+ *= /= %=;
(5)自增 ++ 和自減 -- 每次變化1:
- ++a 先運算,再執行
- a++ 先執行,再運算
8. 數據類型轉換
(1)隱式類型轉換:
① 字符轉數值: -、*、/、%;
② 數值轉字符:+;
③ 其他轉 boolean:if(){} 括號中的隱式轉換
- 非 0 為 true,0 為 false;
- 所有非空字符(即"",而不是" ")為 true,空字符為 false;
- undefined 為 false;
- 所有對象和數組(包括{},[],除了 null)都為 true;
- NaN 為 false;
- null 為 false;
④ 其他
- true 會轉成1,false 會轉成0;
- NaN 與任何值(除了字符)運算得到 NaN;console.log(1 + "1");//11 console.log(2 + false);//2 false -> 0 console.log(1 + true);//2 true-> 1 console.log(true + false);//1 console.log(undefined + 1);//NaN console.log(undefined + NaN);//NaN console.log(undefined + null);//NaN console.log(null + 1);//1 null -> 空
(2)顯式(強制)類型轉換
① 字符轉數值:Number()、parseInt()取整、parseFloat()取浮點數、Math.round()四舍五入取整
-
parseInt() 和 parseFloat() 轉換規則:
從左到右依次檢測字符,遇到數字就轉,遇到字母就停,第一位是字母就是 NaN; -
Number():
嚴格轉換,小數點也能轉換,只要出現一個非數字的字符,無論在哪個位置,都是 NaN。
② 數值轉字符: +""、toString()轉成字符、toFixed(n)四舍五入且保留n(n>=0)位小數
var num = 10; var str = num + ""; var str = num.toString(); var str = num.toFixed();9. 解決精度缺失問題
var n = 0.1 + 0.7; n = parseFloat(n.toFixed(1))10. 進制的轉換
(1)十進制轉其他: toString()
var num = 110; console.log(num.toString(2));//十進制轉二進制 1101110 console.log(num.toString(8));//十進制轉八進制 156 console.log(num.toString(16));//十進制轉十六進制 6e(2)其他轉十進制: parseInt()
var str = "110"; console.log(parseInt(str,2));//二進制的轉十進制 6 console.log(parseInt(str,8));//八進制轉十進制 72 console.log(parseInt(str,16));//十六進制轉十進制 272(3)其他轉其他
先轉成十進制,再用 toString() 進行轉換;
11. undefined 和 not a defined
(1)undefined: 定義了沒賦值;
(2)not a define: 未定義、一種報錯;
二、程序的結構-單雙分支
邏輯的不同,程序分為三種結構:順序結構、分支結構、循環結構;
2.1 分支結構
1. 單分支
if(判斷條件){},只要“判斷條件”為真,就會執行花括號中的操作。
- 判斷條件為真,可以是一個 boolean值為 true 的變量,非 0 的數字,具體可以參考 第一點里面的第8條-數據類型轉換-其他轉 boolean。
2. 雙分支
- if(){}else{}
- 三目表達式:條件 ? 條件為真時的操作 : 條件為假時的操作;
3. 多分支
(1)if()
if(){ } else if{ } else{ }(2)switch(){}
//switch語句名 //()要判斷的值 //{}要執行的內容 //default:不是必須的,常只有一個,放在最后,不需要加break; switch(變量){case 變量值0:操作;break; case 變量值1:操作;break;default:當 case 條件不滿足是執行的操作(默認操作); }- case 穿透: 當某一條 case 判斷成功時,執行了當前 case 后的語句,后面所有的 case 都不再驗證判斷條件,直接執行后面所有的語句;var n = 2; switch (n){case 1:console.log("星期一");case 2:console.log("星期二");case 3:console.log("星期三");case 4:console.log("星期四"); }//打印結果 星期二 星期三 星期四
- 阻止 case 穿透: break 在 switch 中專門用來阻止 case 穿透。
2.2 循環結構
1. 循環三要素:
(1)聲明計數器,比如:var i;
(2)計數器的改變;
(3)停止條件;
2. 循環語句
(1)while(){}
//while語句名 //()執行條件、停止條件 //{}執行語句、循環體 var i = 0; while(i<10){console.log(i);//0 1 2 3 4 5 6 7 8 9i++;//計數器常放最后console.log(i);//1 2 3 4 5 6 7 8 9 10 } //當 i<10 時,執行循環體,否則不執行。執行次數 10- 求100-999之間的水仙花數://水仙花數: a^3 + b^3 + c^3 = abc; var i = 100; while(i<1000){var a = i%10; //取個位數var b = parseInt(i%100/10); //取十位數var c = parseInt(i/100); //取百位數if(i == a*a*a + b*b*b + c*c*c){console.log(i)}i++; }
(2)do{}while(){}
特性:不管條件是真還是假,do 和 while 都會進行循環;
(3)for(){}
//for 語句名 ()條件組 {}循環體 for(var i=0;i<10;i++){console.log(i);//0 1 2 3 4 5 6 7 8 9 }3. do-while 和 while的區別
do-while不管任何情況下都至少會執行一次。
var i = 0; do{console.log("do執行:"+ i); //0 1 2 3 4 5 6 7 8 9i++; } while ( i < 10){console.log("while執行:"+ i); //104. 死循環:
無法替自身控制結束的循環,稱為死循環;
死循環的應用:每次判斷一個條件,直到滿足條件,利用 break 跳槽循環(常使用 while())。
- 籃球從5米高的地方掉下來,每次彈起的高度時原來的30%,經過幾次彈起,籃球的高度是0.1?var i = 0; var h = 5; while(true){h = h * 0.3;i++;if(h<0.1){break;} } console.log(i); //4
5. 循環中的關鍵字
(1)break,跳出當前循環、結束當前循環,不再執行剩余代碼。
(2)continue,跳過本次循環,用于停止當次循環,回到循環起始處,進入下一次循環操作。。
三、函數
概念: 函數是由事件驅動的,或者當它被調用時可執行的可重復使用的代碼塊;
1. 函數的使用
(1)創建函數
- 聲明式 創建函數: function 函數名(){//...}
- 賦值式(也叫字面量式) 創建函數: var 函數名 = function(){//...}
(2)函數調用方式:
- 自動執行: 函數名();
- 事件執行: obtn.onclick = 函數名;
(3)函數執行時機:
- 任何情況下,只要 函數名(),立即執行;
- 當需要用事件觸發函數時,不能加小括號,加了就會立即執行;
(4)使用/執行: 函數名();
<button>按鈕</button> var obtn = document.querySelector("button"); obtn.onclick = say;function say(){console.log("hello"); }(5)函數的好處:
① 重復使用;
② 選擇執行;
③ 忽略細節(就想空調一樣,不會組裝,但是會使用);
2. 函數分類
(1)有名函數: function 函數名(){};
(2)無名函數: funtion(){};
(3)匿名函數: (function(){})()
- 區別:
① 無名函數: 不能直接寫,必須通過事件調用,或者作為參數、返回值等使用;
② 匿名函數: 會立即執行,自動執行(即:不用主動調用,自己執行);
3. 函數的參數
形參: 形式的參數,函數定義時,小括號內的參數;
實參: 實際的參數,函數執行時,小括號內的參數;
(1)實參數量 = 形參數量,參數一一對應;
(2)實參數量 > 形參數量,多出來的實參到 argument 中;
(3)實參數量 < 形參數量,多出來的形參是 undefined;
4. arguments
(1)偽數組:
- 理解:偽數組像數組一樣有 length 屬性,也有 0、1、2、3 等屬性的對象,看起來就像數組一樣,但不是數組。
- 特點:
① 具有 length 屬性;
② 按索引方式存儲數據;
③ 不具有數組的 push()、pop() 等方法; - 偽數組轉換為真數組:
① 方法一:Array.prototype.slice.call(偽數組);
② 方法二:Array.prototype.slice.apply(偽數組);
③ 方法三:Array.prototype.slice.bind(偽數組);
④ 方法四:Array.from(偽數組),返回的就是真數組;
(2)arguments 是一個偽數組,接收所有實參。
function fn(a,b){console.log(a); //4console.log(b); //6console.log(arguments);//Arguments(4) [4,6,8,3] } fn(4,6,8,3)- 示范將偽數組變成真數組:function fn(a,b){console.log(arguments);//Arguments(4) [4,6,8,3]var arr = Array.prototype.slice.call(arguments);console.log(arr); //[4,6,8,3] } fn(4,6,8,3)
(3)arguments.callee 保存了自身所在的函數,“遞歸”中使用(但是后期遞歸舍棄了該方法);
function fn(a,b){console.log(arguments.callee);//[4,6,8,3] } fn(4,6,8,3)(4)運用場景:無法確定實參的個數是多少時。
//求任意個數字的和 function fn(){var sum = 0;for(var i = 0; i<arguments.length; i++){sum += arguments[i];} } fn(4,6,8,3)5. return
把函數里面的數據 返回到 函數外面,使我們可以在函數外面拿到函數里面的數據。
(1)作用:① 終止循環;② 返回值;
function fn(){return 123; } var a = fn(); console.log(a);//123 console.log(fn());//123- 閉包具體在后面提及,這里寫一個示例。function a(){var m = 0;return function(){m++;console.log(m)};} console.log(a()); //打印結果:返回的是return后面的函數,不包括 var m = 0;這一條語句。 //? (){ // m++; // console.log(m) //} a()(); //11 這樣相當于執行函數a的整個部分,所以多次調用,會一直先讓m=0,再去執行return語句 a()(); //11 //從上面的打印結果,我們可以看到打印a()的結果是一個函數。 function a(){var m = 0;return function(){m++;console.log(m)};} var b = a(); //將這個函數結果定義一個新的變量保存起來 b(); //11 b(); //12 b(); //13//上面這種保存函數的方法,執行結果就相當于 //function a(){var m = 0;function b(){ //變量m和函數b組成了一個閉包return m++;} //} console.log(b()); //因為函數b的返回值是return,要想查看結果,就要console.log(b());而不能直接b() console.log(b()); //類似數組方法sort()的執行過程 console.log(b());
(2)return 的幾個返回值:
① return true;,返回正常的處理結果;終止處理。
② return false;,返回錯誤的處理結果;終止處理;阻止提交表單;阻止執行默認的行為。
return false; 只在當前函數有效,不會影響其他外部函數的執行。
③ return;,把控制權返回給頁面。
(3)break,continue 和 return 的用法及區別:
| 相同之處 | 三個都會將此時進行的語句停止。 | ||
| 不同之處 | break 是立即結束語句,并跳出語句,進行下個語句執行。 | continue 是停止當前語句,并從頭執行該語句。 | return 停止函數。 |
| 使用環境 | break 和 continue 是用在循環或switch語句中,用來退出循環。 | return 是用在函數語句中。return 語句應用范圍只能出現在函數體內,出現在代碼中的其他任何地方都會造成語法錯誤! | |
| 舉例 | for(i=0; i<5; i++){ ? if(i == 3){ ? ? break; ? } ? console.log(i); } | for(i=0; i<5; i++){ ? if(i == 3){ ? ? continue; ? } ? console.log(i); } | function format(d){ ? if(d<10){ ? ? return “0” + d; ? } else { ? ? return d; } |
| 返回值 | 0 1 2 | 0 1 2 4 | |
| 結果分析 | 當 i=3 時,直接退出for這個循環。這個循環將不再被執行!直接進入下一個語句。 | 當 i=3 時,直接跳出本次for循環。繼續執行這個循環語句的后面的循環條件。 | 語句結束函數執行,返回調用函數,而且把表達式的值作為函數的結果。 |
6. 作用域
作用域分為:全局作用域、局部作用域、塊級作用域,這里主要講前兩種。
(1)全局作用域: 變量在函數外定義,即為全局變量。全局變量有全局作用域:網頁中所有腳本和函數均可使用。
var carName = " Volvo";// 此處可調用 carName 變量 function myFunction() {// 函數內可調用 carName 變量 }- 如果變量在函數內沒有聲明(沒有使用 var 關鍵字),該變量為全局變量,而全局變量一般存到 window 中,我們通常會省略window。
以下實例中 carName 在函數內,但是為全局變量。myFunction(); // 此處可調用 carName 變量 function myFunction() {carName = "Volvo";// 此處可調用 carName 變量 } console.log(carName); //Volvo console.log(window.carName); //Volvo
(2)局部作用域: 變量在函數內聲明,變量為局部作用域。每一個函數都有一個局部的作用域,局部作用域只能在函數內部訪問。;
// 此處不能調用 carName 變量 function myFunction() {var carName = "Volvo";// 函數內可調用 carName 變量 }① 因為 局部變量只作用于函數內,所以在不同的函數內部可以使用相同名稱的變量。
② 局部變量在函數開始執行時創建,函數執行完后局部變量會自動銷毀。
函數內改變的只是該函數內定義的局部變量,不影響函數外的同名全局變量的值,函數調用結束后,局部變量占據的內存存儲空間被收回,而全局變量內存存儲空間則被繼續保留。
③ 當你在 全局 和 局部 同時用 var 命名同名變量時,那么同名局部變量會在其所在函數內屏蔽全局變量,而優先使用局部變量。
var a = "10"; function fn() { var a ="20";console.log(a) } fn(); //20 console.log(a); //10 這里的a為全局變量(3)變量生命周期
① JavaScript 變量生命周期在它聲明時初始化。
② 局部變量在函數執行完畢后銷毀。
③ 全局變量的生命周期一直存在,在頁面關閉后銷毀。
- 將全局變量 變成 局部變量的方法:
將變量放到匿名函數中。(function(){var a = 3; })() A、在匿名函數中,全局變量可以被匿名函數中的函數訪問、使用;
B、沒有真正聲明全局變量時(比如變量在函數內沒有用 var 聲明就賦值),也不會污染整個全局變量空間、占用內存。
7. 變量提升
在 JavaScript 中,變量可以在使用后聲明,也就是變量可以先使用再聲明。
函數及變量的聲明都將被提升到函數的最頂部。
(1)變量提升
所有用 var 聲明的變量都存在提升,提升到作用一開始的位置,在寫了 = 號的位置賦值(即提前聲明,在原本賦值的地方賦值);
- 相當于:var a; console.log(b);//b is not defined console.log(a);//undefined a = 10; console.log(a);//10 console.log(b);//b is not defined
(2)函數提升
① 聲明式: 整個函數提升(即提前聲明,提前賦值),整個代碼塊提升到它所在的作用域的最開始執行;
- 相當于:function fn(){console.log("hello"); } fn();//hello
② 賦值式(字面量式): 提升變量(即提前聲明,但是沒有提前賦值);
fn();//fn is not a funtion var fn = function(){console.log("world"); }- 相當于:var fn; fn();//fn is not a funtion fn = function(){console.log("world"); }
這里有一道題,結合作用域以及變量提升的知識點,請你給出打印結果。
console.log(v1); var v1 = 100; function foo() {console.log(v1);var v1 = 200;console.log(v1); } foo(); console.log(v1);//打印結果: //undefined //undefined //200 //100- 解釋一下,上面代碼相當于下面這段代碼的縮寫:var v1; //在全局上,我們可以看到 v1 已經被 var 聲明定義了,所以要被提升。 console.log(v1); //undefined var v1 = 100; function foo() {var v1; //在局部作用域中,v1 被 var 聲明,所以提前到作用一開始的地方。console.log(v1); //undefinedvar v1 = 200;console.log(v1); //200 } foo(); console.log(v1); //在全局獲取不到局部作用域中的變量,這里的 v1 是全局變量
8. 遞歸
(1)遞歸就是在自身內部調用自己;
(2)缺點: 耗性能,邏輯稍微不太好理解;
-
遞歸計算階乘
//3*2*1 function fn(n){if(n == 1){return 1;} else {return n*fn(n-1);} } fn(3); -
斐波那契數列:1,1,2,3,5,8,13,21,34…
//寫一個數字n,找到第 n 個斐波那契數列; function fn(n){ if( n == 1 || n== 2){return 1;} else {return fn(n-1) + fn(n-2); } fn(3);
下一篇—— js筆記(二)對象和構造函數、數組、this
總結
以上是生活随笔為你收集整理的js笔记(一)js基础、程序结构、函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vue笔记(二)Vue-class与st
- 下一篇: js笔记(三)ES5、ES5新增的数组的