JavaScript基礎
- 2021 年 3 月 3 日
- 筆記
- 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種原始數據類型:
- undefined, 未定義,尚未賦值
- null 空
- boolean 布爾類型
- number 數字(浮點型,包含小數點的實數)
- 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中推出了標準的模塊寫法
- 模塊文件中export
- 在使用的地方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>