JavaScript基礎

JavaScript:動態腳本語言

  • 弱類型

  • 動態類型

    I/o:文檔交流

​ 由三部分組成:

  • ECMAScript(語言核心)

  • DOM (文檔對象模型)

  • BOM (瀏覽器對象模型)

  • 瀏覽器渲染 html 是從上到下的

    • 一般來說,會將 script 放到 head 中,但是為了渲染速度,很多時候,會放到 body 的最後
    • 如果 script 標籤不閉合,會導致頁面渲染出問題

在JS執行中都是單線程執行,所以代碼的執行可以說是自上而下,如果前一段的代碼出現問題,就會導致下一段代碼無法執行,對於用戶而言就是卡死現象,所以在JS執行機制引出了異步執行操作。

 var x = 1;  // 賦值
//在js中,number 表示一切數字,包括整數和浮點數。全都是 64 位。
//undefined表示未定義, null 表示為空
//boolean 表示布爾		只有true和false

1.1函數:就是 執行邏輯 的一種封裝。

function mysum(a,b){};    mysum(1,2); // 往裡寫入參數,返回1,2
var abs = function(a,b){};
1.1.2預定義函數:

​ parseInt();將字符串轉換成整數,無法解析則返回NaN

​ parseFloat();將字符串轉換成浮點數,無法解析則返回NaN

​ eval(); 將字符串參數作為JavaScript代碼執行

​ isNaN(); 判斷指定內容是否為非數字,只有純數字組成的返回false,否則返回true

​ 例:isNaN(NaN); //true

​ isNaN(1122); /false

​ escape()函數的作用是將一些特殊字符轉換成ASCII碼

​ unescape()函數的作用是將ASCLL碼轉換成字符

1.1.3 回調函數
 function mysum(a,b,f){ return f("出錯了,")} //f是一個函數,用來表示出錯時候的邏輯
											//實現邏輯的分離
								//一旦執行到return時,函數就執行完畢,並將結果返回。
1.1.4 遞歸函數
function rec(){
    console.log("hello");
    if(Math.random() > 0.999){
        ruturn;
    }
    rec();
}
rec();									//它是計算機進行計算更加本質的一種行為
                                        //它可以完全替換掉循環語句
                                        //燒腦,不夠直觀
                                        //燒內存,爆棧。沒有遞歸做進一步優化,尾遞歸優化
                                        //遞歸必須要有邊界條件 !!!
1.1.5 箭頭函數
x => x * x
//等價於
function (x) {
    return x * x;
}
1.1.6 generator (生成器) : ES6引入的新的數據類型,可返回多次
 function* foo(x){
   yield x + 1;
    yield x + 2;
    return x + 3;   //generator由function*定義
     				//還可以用yield返回多次
 }
 調用generator對象的方法:
	1.不斷調用generator對象的next()方法
    	var f = fib(5);
		f.next(); // {value: 0, done: false}
		f.next(); // {value: 1, done: false}
		f.next(); // {value: undefined, done: true}
//另外,generator可以把異步回調代碼變成'同步'代碼,要等AjAx以後才能知道

2.1 數據類型

2.1.1 JS中的5種原始數據類型:
  1. undefined, 未定義,尚未賦值
  2. null 空
  3. boolean 布爾類型
  4. number 數字(浮點型,包含小數點的實數)
  5. string 字符串
 var a = a;
 let  a = 1; //優先使用 const,在數據需要修改的時候,使用 let,迫不得已 var
 const a;    //千萬不能忘掉 var 的原理跟使用方式,因為面試需要
			//const 賦值後,將不能再賦值,否則將報錯
			//將各種變量放入函數中,叫做閉包,提高安全
//當一個變量沒有聲明var,let,const類型時,它將會是一個全局變量,會產生調試的錯誤
2.1.2 在ES6中提出了變量定義的關鍵詞:(let/const)

​ 區別: 塊級別的作用域

​ 優先使用const,在數據需要修改的時候,使用let,迫不得已var

​ 千萬不能忘記var的原理跟使用方法,因為面試需要

3.1.1 詞法作用域

​ 即靜態綁定

​ 好處:

  • 函數定義時綁定了某個變量,後面就不會發生變化
  • 便於理解,便於調試,不容易出錯
3.1.2 閉包

​ 閉包的根源是詞法作用域

​ 主要目的:

  • 為了保護變量,不被外部修改
  • 為了使數據在內存中駐留
    • (可能引發的內存泄漏)
var count = 1;  //count是暴露在外的,可能被篡改,不安全

function Counter(){
    let count = 1;
    //使用閉包,保護count的安全
    //能夠確保count在函數調用之後會一直存在,不會被釋放
}

3.1 window對象/雜項

3.1.1 window:瀏覽器窗口對象

3.1.1 arguments:它只在函數內部起作用,並且永遠指向當前函數的調用者傳入的所有參數
 function foo(x) {
    console.log('x = ' + x); // 10
    for (var i=0; i<arguments.length; i++) {
        console.log('arg ' + i + ' = ' + arguments[i]); // 10, 20, 30
    }
}
foo(10, 20, 30);  // 利用arguments 可以獲得調用者傳入的所有參數,即使函數不定義任何參數,還是可以拿到參數的值
 //實際上arguments最常用於判斷傳入參數的個數。你可能會看到這樣的寫法:
	function foo(a, b, c) {
    if (arguments.length === 2) {
        // 實際拿到的參數是a和b,c為undefined
        c = b; // 把b賦給c
        b = null; // b變為默認值
    }
    // ...
}
3.1.2 rest參數 (ES6新標準)
	function foo(a,b,...rest){
        console.log('a='+a);
        console.log('b='+b);
        console.log(rest);
    }  
foo(1,2,3,4,5) //結果:a=1,b=2,Array[3,4,5] 
		//多餘的參數將以數組形式交給變量rest,所以不再需要arguments我們就獲取去了全部參數
3.1.3 ES6中解構賦值
	var [x,y,z] = ['hello','java','es6'];
	console.log('x = ' + x + ', y = ' + y + ', z = ' + z);
	//輸出x = hello, y = jave, z = es6

4.1 循環與判斷

4.1.1 for循環
	var att = ['xx',11,'ss','z'];
	var i;
	for(i=0;i<att.length;i++){
        var aa = att[i];
        console.log(aa);
    }  //遍歷出 xx,11,ss,z
		//breck表示退出循環
	for(;;){ // 是個死循環
        ..
    }
4.1.2: for..in循環可以把一個對象的所有屬性依次循環出來
 var o = {
     name:'xx',
     age:12,
     city:'jiangxi'
 };
var o2= [1,2,'xx'];
for(var key in o){
    console.log(0key);  // name,age,city  只是遍歷屬性,並不是遍歷出值
    console.log(02[i])
}xxxx

 
4.1.3 switch
	switch(age){
        case 18:console.log('xxx');
        case 22: console.log('xxxxx');
            break;
    }
4.2.1 if判斷
if (){  //默認使用 === 進行判斷,即既判斷類型,又判斷值
    
    }else if(){
             
     }else{
    
}
4.3.1 Swith/Case
switch(age) {
case 18:
    console.log("you should study")
case 22:
    console.log("you should go to work")
    break;  //使用 break 跳出分支
case 60:
    console.log("you should have a rest")
    break;
default:
    console.log("我沒有什麼好提醒你的")
} //使用 default 表示其他分支都不匹配的情況,可以省略
4.4.1 三目運算
  • 簡短,快捷
  • 沒有return,不能寫複雜句式
boolend? 分支1:分支2
條件? 判斷1:判斷2

5.1 基於原型鏈的繼承: proto

 var na = {
     play: function(){console.log('吶')}
 }
 var xiaoming = {
     name:'小明',
     age:18
 }
 xiaoming._proto_ = na;  
//將xiaoming的爸爸指定為na,那麼,xiaoming將可以用na的所有屬性方法
//通過 __proto__ 去尋找其父

編程的潮流是簡便、高效率,

​ 為了讓事情變得簡化,我們可以寫入函數中,使用函數消除冗餘

var person = {
    ear:function() { console.log('xx')}
}
function(name,age){
    var a = {
        name:name,
        age:age
    }
}
a._proto_=person;  //指定父類為person,獲取父類的屬性.
return a ;

var xiaohong = createStudent('小紅',18);  ...

再如JS提供的一種內部語法

 function person(){
     this.ear = function() { console.log('xx')}
 }
function ag(name,age){
    this.name = name,
    this.age = age
}
ag.prototype = new Person();
var xiaohong = new ag('小紅',18);

6.1 JavaScript核心內置對象

String -字符串
Math -處理數學運算
Date -提供操作日期和時間的方法
Array - 數組模型,儲存數據
Function - 提供構造新函數的模板
Object - 包含js對象所共享的基本功能
RegExp - 表述了一個正則表達式對象
6.1.1Math :主要作用在Number, 進行數學運算
Math.randon();//求隨機數
Math.pow(4,2)  //4的二次方
Math.sprt(4) //開根號2
Math.exp(2); //自然指數
Math.randon().toFixed(2);//取前兩位數. 
6.2.1Date:時間
let d = new Date();
let d = new Date('2010-08-04');
let d = new Date('1995-12-17T03:24:00');
let d = new Date("October 13, 1975 11:13:00");
let d = new Date(79, 5, 24);            // 年月日
let d = new Date(79, 5, 24, 11, 33, 0); // 年月日時分秒(創建指定日期時間)
d.setFullYear(2010,0,14);    // 2010.1.14

6.3.1 RegExp :正則匹配
var re2 = new RegExp('ABC\\-001');

var re = /^\d{3}\-\d{3,8}$/;
re.test('010-12345'); // true
6.4.1 數組的建立
  
var arr = [1, 2, "hello", true]; 
arr.length      // 4  從0開始
arr.concat([33, 44]) // [1, 2, "hello", true, 33, 44]

arr.flat(); // 將其壓平
arr.includes(); // 判定是否存在某個元素
arr.indexOf/lastIndexOf(1);  // 判定某個元素的序號

arr.slice();  // 複製
arr.splice(3); // 刪除、添加,默認行為是刪除從 3 到最後一位的元素,返回被刪除的元素組成的數組
arr.splice(3, 1); // 刪除多少個元素
arr.splice(2, 0, 11111); // 添加

arr.reverse(); // 將數組內元素反向排序,注意,它是一個破壞性的函數
arr.sort();    // 排序,破壞性的函數
arr.sort(function (a, b) { if (a > b) return -1; else return 1 });
	
6.4.2 數組的基本語法
var arr = [1, 2, "hello", true];
arr.length      // 4
arr.concat([33, 44]) // [1, 2, "hello", true, 33, 44]

arr.flat(); // 將其壓平
arr.includes(); // 判定是否存在某個元素
arr.indexOf/lastIndexOf(1);  // 判定某個元素的序號

arr.slice();  // 複製
arr.splice(3); // 刪除、添加,默認行為是刪除從 3 到最後一位的元素,返回被刪除的元素組成的數組
arr.splice(3, 1); // 刪除多少個元素
arr.splice(2, 0, 11111); // 添加

arr.reverse(); // 將數組內元素反向排序,注意,它是一個破壞性的函數
arr.sort();    // 排序,破壞性的函數
arr.sort(function (a, b) { if (a > b) return -1; else return 1 });

var xx = [1,3,2,'hello'];
xxs.indexof(1);  //元素1的索引為2

var a = [1,2,3,4,5,6,7,'ss'];
a.slice(2,4);   //從索引2開始到4之內的所有值,不包括4  為3,4

push()向Array的末尾添加若干元素
var arr = [1,2];
arr.push('a','c');
arr; //[1,2,'a','c']

unshift()向Array的前面添加若干元素
arr.unshift('x'); //  ['x',1,2]

pop()則把Array的最後一個元素刪除掉
arr.pop();  //將'c'刪除  ,重複多次,將多次刪除
shift()則把Array的第一個元素刪除
arr.shift(); // 將1刪除,重複多次,多次刪除

sort()對Array進行排序,會直接修改當前Array的元素位置
arr.sort();

reverse()把整個Array的元素反轉排序
arr.reverse();
	
splice()是修改Array的萬能方法,可以從指定的索引開始刪除若干元素,然後再從該位置添加若干元素
例:var arr = [1,2,'xxx'];
	arr.splice(1,2,'xxx') 從1開始往後刪除兩個,包括1本身開始

concat()將Array和另一個Array連接起來,返回一個新的Array
var a = [1,2,3,4];
var b = a.concat([22,22,33]); //返回[1,2,3,4,22,22,33]

join()將Array的元素連接起來,返回連接的字符串
var a = ['a','x','s'];
a.join('-'); // a-x-s  如果不是字符串,將自動轉換成字符串後再連接
	
6.5.1 typeof :獲取對象的類型
typeof 123;//number
typeof 'str';//string
typeof null;//object
6.6.1包裝對象
var n = new Number(123); //生成新的包裝類型
//雖然看起來一樣,但類型已經變成object,當原始和包裝後的對象用=== 比較,會返回false
//所以少用包裝對象
//用parseInt()或parseFloat()來轉換任意類型到number;
6.7.1 window對象:充當全局作用域,而且表示瀏覽器窗口
	window.innerWidth //頁面長度
	window.innerHeight //頁面高度
6.8.1 JSON語法

在JSON出現之前,大家一直用XML來傳遞數據

//JSON語法是JAVAScript對象表示語法的子集
//格式為:
		JSOn名稱:值   如:"key":"value"
//key[0].value 可訪問 ,JSON與XML都用於接收web服務端的數據
--JSON實例:
{
    "sites": [
    { "name":"菜鳥教程" , "url":"www.runoob.com" }, 
    { "name":"google" , "url":"www.google.com" }, 
    { "name":"微博" , "url":"www.weibo.com" }
    ]
}  //JSOn更簡短,不需要結束標籤,可以使用數組
	//XML需要XML解析器來解析,JSON直接用JavaScript函數來解析
	//通過JSON.parse(); 將JSON字符串轉換成JS對象
	//JSON.stringify(); 將JS值轉換為JSON字符串
--XML實例:
    <sites>
      <site>
        <name>菜鳥教程</name> <url>www.runoob.com</url>
      </site>
      <site>
        <name>google</name> <url>www.google.com</url>
      </site>
      <site>
        <name>微博</name> <url>www.weibo.com</url>
      </site>
    </sites>

7.1 DOM節點:文檔對象類型

第一種:
//在操作一個DOM節點前,我們需要通過各種方式先拿到這個DOM節點。最常用的方法是:
document.getElementById('xx')   //id
document.getElementsByTagName('xx')  //元素標籤 
document.getElementsByClassName('div') //CSS選擇器


document.write(x.getAtteribute("屬性名"))//返回目標對象指定屬性的屬性值
x.setAttribute("title","圖書列表"); // 修改元素節點的屬性值
x.removeAttribute()  //刪除指定元素的屬性


 //小知識:因為這些方法繁瑣,不夠簡便靈活,所以出現了第三方的框架,如jQuery.簡化了dom操作,$();
查找節點的另一種:Element節點
//querySelector 只返回一個
//querySelectorAll 返回一個NodeList 類似Array的對象
element.querySelector("div")/(".xxx")/("#xx")
						/(div > span)/(div span)
element.querySelectorAll('img');
document.querySelector('#test-js');

			
7.1.1 定位節點
m.childNodes;  // 顯示所有的孩子節點
m.children;    //顯示孩子節點
m.childNodes[2] //使用數組,獲取第2個孩子節點
m.parentNode; //引用當前節點的父節點
m.childNodes[3].prevSibling; // 上一個兄弟節點
m.childNodes[3].nextSibling; // 上下個兄弟節點

 test.firstElementChild // 獲取節點test下第一個子節點
 test.lastElementChild; //獲取最後一個子節點


// 先定位ID為'test-table'的節點,再返回其內部所有tr節點:
var trs = document.getElementById('test-table').getElementsByTagName('tr');


7.1.2 修改

在選中了某個節點後,我們可以修改:

 m.firstChild.nodeValue = 'xxx';
m.childNodes[1].innerText = 'xxxxxxx';
 //關鍵詞 : innerText ,nodeValue
innerHTMl :可以修改DOM節點的內容,還可以修改DOM節點的子樹
7.1.3 新建,附加節點
//添加一個文本節點:appendChild
	var t = document.createTextNode('世界和平');
	m.appendChild(t);
//appendChild:把一個子節點添加到父節點的最後一個子節點
//insertBefore : 子節點插入指定位置
xx.insertBefore(子節點,xx) //將子節點插入xx節點的上面
list.appendChild(js); //父節點.appendChild(子節點);

//添加一個元素節點:insertBefore
	m.insertBefore();

//添加一個注釋節點:appendChild
	m.appendChild();	
//創建一個節點
var a = document.createElement('p');
a.id = 'aa'; //給節點添加id
a.innerText = 'xx';

7.1.4 替換,刪除
	//必須從父節點開始替換,刪除
m.replaceChild(); //替換節點
m.removeChild(); //刪除節點
7.2.1 API
attributes 獲取節點上的所有屬性
getAttribute/setAttribute 獲取/設置屬性

8.1 事件

8.1.1 event

​ event.x,event.y,獲取鼠標的位置

8.2.1 瀏覽器事件
  • window.onload — 瀏覽器載入文檔事件
  • window.onfocus — 瀏覽器獲得焦點
  • window.onblur — 瀏覽器失去焦點
  • window.onscroll — 瀏覽器拖動滾動條
  • window.onresize –改變窗口尺寸
8.3.1 HTML元素事件

用戶與頁面的交互發生在按鈕,圖片等系列HTML元素上的響應

​ 例:

onclick -鼠標單擊
ondbclick -鼠標雙擊
onmmouseout - 鼠標移出鏈接所在的位置
onmouseover - 鼠標經過鏈接所在的位置
onmouseup - 鼠標在鏈接的位置放開
onkeydown - 鍵被按下
onkeyup - 鍵被送開
onblur - 失去焦點
onfocus - 獲得焦點
onchange - 文本內容改變
onkeypress - 按下並放開該鍵

​ 當定義一個函數時,我們可以通過定時,來委託給瀏覽器調用

function xxx(){
    console.log('時間延長');
}
//通過定時任務的方式,委託給瀏覽器調用:
setTimeout(xxx, 3000);
setInterval(xxx, 3000);
//通過事件的方式,委託給瀏覽器監聽並觸發調用:
document.querySelector('button').onclick = xxx;

9.1 異步請求:AJAX

AJAX=異步JavaScript和XML

是用於創建快速動態網頁的技術

9.1.1 XMLHttpRequest對象
XMLHttpRequest用於在後台與服務器交換數據
 //創建XMLHttpRequest對象
	var iable = new XMLHttpRequest();
	//在陳舊的IE5、IE6中,用ActiveXobject
	var iable=new ActiveXObject("Microsoft.XMLHTTP");

//使用open()、send()方法將請求發送到服務器
	open(method,url,async)
如:xmlhttp.open("GET","ajax_test.asp",true);
							//method:請求的類型;GET 或 POST
							//url:文件在服務器上的位置
							//async:true(異步)或 false(同步)

	send(string)     		//string:僅用於 POST 請求

10.1作用域及模塊化

var:使用var定義的數據作用域,是函數級別的.

let/coust:塊級作用域 優先使用級:const>let>var

在ES6中推出了標準的模塊寫法

  1. 模塊文件中export
  2. 在使用的地方import
//模塊的導出
var name = 'tom';
var hello = function(){alert('Hello,World')};
export {name,hello};
或:在聲明時,一齊導出
export var aa = 'xx';
export default 'heelo world'; //默認導出,只可一個

//模塊的引用
<script type="module">
	import{name,heelo} from "js的路徑";
	import * as x from "路徑";  //通過as 來進行賦值或者換命名
	//盡量將模塊分成多個js文件,每個js文件可成一個模塊;
    </script>