萬丈高樓拦盹,始于壘土,所以基礎(chǔ)語法就是我們技術(shù)的根基舍哄,今天我們來聊聊JS的基礎(chǔ)語法
溫馨提示:文章結(jié)構(gòu)如下宴凉,閱讀完可能需要花費5分鐘
一、JS的數(shù)據(jù)類型
二表悬、變量
三弥锄、內(nèi)置對象
進入正文
一、JS的數(shù)據(jù)類型
數(shù)據(jù)類型可分為2類:基本數(shù)據(jù)類型與引用數(shù)據(jù)類型
基本數(shù)據(jù)類型包括:Undefined蟆沫、Null籽暇、String、Bool饭庞、Number戒悠、Symbol
1.1基本數(shù)據(jù)類型的特點
- 值不可改變
- 存放在棧中
1.2 Undefined
特點 : 變量原始值、函數(shù)默認返回值舟山、訪問對象上不存在的屬性
1.3 Null - 空對象
知識點1: 我們的內(nèi)存地址可以識別數(shù)據(jù)類型
000 - 對象绸狐,數(shù)據(jù)是對象的應(yīng)用
1 - 整型,數(shù)據(jù)是31位帶符號整數(shù)
010 - 雙精度類型累盗,數(shù)據(jù)是雙精度數(shù)字
100 - 字符串寒矿,數(shù)據(jù)是字符串
110 - 布爾類型,數(shù)據(jù)是布爾值
null的前3位也是000,只能通過
Object.prototype.toString.call(null)
知識點2:== 只是比較值若债,類型自動轉(zhuǎn)化 === 比較值 且比較數(shù)據(jù)類型
const a = 1;
const b = true;
console.log('==',a == b); // true
console.log('===',a === b); // false
1.4 string都被系統(tǒng)包裝成對象 - 字符串的操作
4. 字符串的方法
4.1 字符操作
const a= '9';
// 獲取Unicode編碼
const unicode = a.charCodeAt(0);
console.log(unicode); //結(jié)果 57
// 根據(jù)unicode編碼符相,取值
console.log(String.fromCharCode(unicode));
4.2 字符串的提取
const name = "JavaScript";
console.log(name.substring(0,4)); // Java
console.log(name.substr(0,4)); // Java
console.log(name.slice(0,4)); // Java
console.log('sdfdsaf345324543'.split('3'));
4.3 字符串的位置索引
const name = "JavaScript";
console.log(name.indexOf('Ja')); // 0
console.log(name.lastIndexOf('a')); // 3
4.4 字符串大小寫切換
const name = "JavaScript";
console.log(name.toLocaleUpperCase());
?console.log(name.toLocaleLowerCase());
4.5 字符串模式匹配 match search replace
const name = "JavaScript";
const reg = /a/g;
console.log(name.replace(reg, 'c'));
4.6 字符串其他操作 concat 拼接 trim - 去空格
console.log('a'.concat('b'));
console.log('ad '.trim());
1.5 Bool、Number都被系統(tǒng)包裝成對象
64位計算機 Number 類型 - 雙精度浮點數(shù) 64位
// 符號位1 + 指數(shù)位11 + 52小數(shù)位 最大最小是2*1024 2*-1023
console.log('最大值:',Number.MAX_VALUE);
console.log('最小值:',Number.MIN_VALUE);
console.log('非數(shù)字:',Number.NaN);
// 5.1 數(shù)據(jù)轉(zhuǎn)換
console.log(Number('23'));
console.log(parseInt('23'));
console.log(parseInt('23'));
// 5.2 四舍五入
console.log('向上取整',Math.ceil(9.12)); // 向上取整 10
console.log('向下取整',Math.floor(9.72)); // 向下取整 9
console.log('四舍五入',Math.round(9.52)); //四舍五入 10
console.log('固定精度',9.54634543.toFixed(2)); // 固定精度 9.55
console.log('固定長度',9.54634543.toPrecision(2)); // 固定長度 9.5
console.log('取整',parseInt('9.54634543')); // 取整 9
- 引用數(shù)據(jù)類型 - Object
特點:
- 實體對象在堆中蠢琳,指向指針在棧中
- 內(nèi)置對象也屬于引用類型(Array/Date/Reg/JSON)
說到Object啊终, 就必須聊一聊深拷貝和淺拷貝
// 1. 淺拷貝 只是拷貝的一個指針指向同一個對象
const obj = {name:"lzb", age: "23", dog: {'dogName': "塞班"}};
const obj2 = Object.assign({},obj);
obj.dog.dogName = "改過的塞班";
console.log(obj.dog.dogName, obj2.dog.dogName);
// 結(jié)果 改過的塞班 改過的塞班
// // 2. 深拷貝,拷貝對象傲须,修改之后不影響原來對象
const obj = {name:"lzb", age: "23", dog: {'dogName': "塞班"}};
const obj2 = JSON.parse(JSON.stringify(obj));
obj.dog.dogName = "改過的塞班";
console.log(obj.dog.dogName, obj2.dog.dogName);
// // 結(jié)果 改過的塞班 塞班
Object常用到的還有一個屬性類型
const person = {};
Object.defineProperty(person, 'name', {
configurable: true, // 能否通過 delete 刪除屬性從而重新定義屬性孕索,或者能否把屬性修改為訪問器屬性。該默認值為 true
enumerable: true, // 表示能否通過 for-in 循環(huán)返回屬性躏碳。默認值為 true
// writable: true, // 能否修改屬性的值搞旭。默認值為 true
// value: "lzb", // 默認值為 undefined
set: function (newValue) { // 在寫入屬性時調(diào)用的函數(shù)散怖。默認值為 undefined
this._name = newValue ? `修改的 + ${newValue}`: "不變的值";
},
get: function () { // 在讀取屬性時調(diào)用的函數(shù)
return this._name ? this._name: "lzb";
}
});
console.log('修改之前的值---',person.name);
person.name = "李四";
console.log('修改之后的值---',person.name);
// 修改之前的值--- lzb
// 修改之后的值--- 修改的 + 李四
到這里基本了解基礎(chǔ)數(shù)據(jù)類型與引用類型,接下來補充一個常用點肄渗,判斷數(shù)據(jù)類型镇眷,
方法這么多,我們到底應(yīng)該使用哪個判斷更加準確
// 2.1 typeof 返回字符串 不能判斷null翎嫡、array
console.log(typeof Symbol()); //Symbol
console.log(typeof new Date()); //object
console.log(typeof null); // object
console.log(typeof [1,23]); // object
// 2.2 instanceof A instanceof B A是否是B的實例 不能檢測null 和 undefined
console.log(([] instanceof Array)); //Array
// 2.3 constructor - 不能檢測null 和 undefined 可能不準確
console.log([1,2,3].constructor === Array);
// 2.4 Object.prototype.toString.call() 最準確
console.log(Object.prototype.toString.call('23')); // [object String]
console.log(Object.prototype.toString.call(23)); // [object Number]
console.log(Object.prototype.toString.call(false)) ; // [object Boolean]
console.log(Object.prototype.toString.call(undefined)) ; // [object Undefined]
console.log(Object.prototype.toString.call(null)) ; // [object Null]
console.log(Object.prototype.toString.call({})); // [object Object]
console.log(Object.prototype.toString.call([])); // [object Array]
console.log(Object.prototype.toString.call(new Function())); // [object Function]
console.log(Object.prototype.toString.call(new Date())) ; // [object Date]
console.log(Object.prototype.toString.call(new RegExp())) ; // [object RegExp]
console.log(Object.prototype.toString.call(new Error())) ; // [object Error]
console.log(Object.prototype.toString.call(document)) ; // [object HTMLDocument]
console.log(Object.prototype.toString.call(window)) ; //[object global] window是全局對象global的引用
最后得到結(jié)果 Object.prototype.toString.call() 最準確
二欠动、變量
- 作用域 : 表示某個變量、某個函數(shù)在某一個地方(代碼塊)有效
ES6 之前 JavaScript 沒有塊級作用域,只有全局作用域和函數(shù)作用域 ES6 之后新增塊級作用域 新增let const
var outScope = "外層數(shù)據(jù)";
function outFunc() {
var inScope = "內(nèi)層數(shù)據(jù)";
function innerFunc() {
console.log(inScope);
}
console.log(outScope);
innerFunc();
}
outFunc();
注意: 所有window對象的屬性擁有全局作用域
- 塊級作用域特點 : 代碼執(zhí)行時遇到花括號惑申,會創(chuàng)建一個塊級作用域具伍,花括號結(jié)束,銷毀塊級作用域
- A.聲明變量不會提升到代碼塊頂
- B.禁止重復(fù)聲明
// 遍歷一
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
}
}
a[5](); // 結(jié)果 5 let i 只在for循環(huán)內(nèi)部有效
// 遍歷二
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
}
}
a[5](); //結(jié)果: 10 因為var 是造成變量提升為全局變量 執(zhí)行完成for 循環(huán)之后 var i = 10 所以不管a[x]() 都是 10
- 變量 var let const
var a = 1000;
// A.ES6 之前的使用 1. 允許重復(fù)的變量聲明:導(dǎo)致數(shù)據(jù)被覆蓋
// B.用var聲明的變量會默認被提升到當(dāng)前作用域的頂部
// C.全局變量會掛載在window
let b = 2; // ES6 新增
// let在全局作用域下定義變量不會掛在到頂層對象window上
// let聲明的變量圈驼,不允許當(dāng)前作用域范圍內(nèi)重復(fù)聲明
// let 沒有變量提升人芽,所以必須先定義,在使用
const c = 3; // ES6 新增
// const 和let特性相同绩脆,唯一不同的是萤厅,const一般指的都是常量,常量的定義是不可改變的變量靴迫,所以用const 申明的變量是不可變的惕味,且只能在定義是進行賦值。
// console.log(window.a); // 1000
// console.log(window.b); // undefined
三. 內(nèi)置對象
3.1 數(shù)組
1.1. 數(shù)組中增加元素
const array = new Array();
array.push("a"); // 往數(shù)組末尾添加新元素
array.push('aa','bb');
array.unshift('b'); // 組最前面添加一個新元素
console.log('數(shù)組----',array);
1.2. 數(shù)組移除元素
array.pop(); // 數(shù)組刪除末尾元素玉锌。
console.log('數(shù)組pop----',array);
array.shift(); // 組刪除最前面一個元素
console.log('數(shù)組shift----',array);
const newArr = array.slice(0,1); // 截取指定元素
console.log('數(shù)組slice----',newArr);
array.splice(1,1); // 移除指定元素index ,
console.log('數(shù)組splice----',array);
1.3. 數(shù)組合并
console.log('合并',[1,2,3].concat(['a','b'])); // 合并之后產(chǎn)生一個新的數(shù)組
1.4 數(shù)組遍歷重要
const eachList = ['a', 'b', 'c', 'a'];
// forEach - 遍歷 當(dāng)前元素名挥、當(dāng)前位置、數(shù)組對象
eachList.forEach(function (value, index, array) {
console.log('forEach - 遍歷', value, index, array);
});
// filter 過濾數(shù)組 - 所有滿足條件的元素 - 可能有多個 - 返回數(shù)組
const resultArray = eachList.filter(function (value, index, array) {
// console.log('filter - 遍歷', value, index, array);
return value === "a";
});
console.log('filter - ',resultArray); // filter - (2) ["a", "a"]
// find 過濾數(shù)組 - -第一個滿足條件的元素 只有一個元素 - 返回元素
const findResult = eachList.find(function (value, index, array) {
// console.log('filter - 遍歷', value, index, array);
return value === "a";
});
console.log('find - ',findResult); // find - a
// map 遍歷數(shù)組 - 加工數(shù)組主守,返回加工之后的數(shù)組
const mapResult = eachList.map(function (value, index, array) {
return value + index;
});
console.log('map - ',mapResult); // map - (4) ["a0", "b1", "c2", "a3"]
// reduce 歸并操作 對數(shù)組每一個元素進行累加躺同,最終返回所有元素之和
const reduceResult = eachList.reduce(function (previousValue, currentValue, currentIndex, array) {
return previousValue + currentValue;
});
console.log('reduce - ',reduceResult); // reduce - abca
// some 對數(shù)組中的每一項執(zhí)行回調(diào)函數(shù),如果該函數(shù)對任一項返回 true丸逸,則停止遍歷,并返回 true , 可以用于判斷
const someResult = eachList.some(function (value, index, array) {
return value == "a";
});
console.log('some - ',someResult); // some - true
// every 對數(shù)組中的每一項執(zhí)行回調(diào)函數(shù)剃袍,如果該函數(shù)每一項都返回 true 才是true 所有
const everyResult = eachList.every(function (value, index, array) {
return value == "a";
});
console.log('every - ',everyResult); //every - false
2.內(nèi)置對象 - JSON
- json 包括2中對象 json對象 key-value json數(shù)組
const person = {name: "lzb", age: 18, score: 100}
console.log('json對象---', person);
const person = [{name: "lzb", age: 18, score: 100}, {name: "ls", age: 18, score: 100}];
- json 對象與字符串的轉(zhuǎn)化
const jsonStr = JSON.stringify(person);
console.log('json -> 字符串', typeof jsonStr, jsonStr);
const jsonValue = JSON.parse(jsonStr);
console.log('\n' + '字符串 -> json', typeof jsonValue, jsonValue);
3.內(nèi)置對象 - Date
-
日期常用操作
const date = new Date(); console.log('當(dāng)前的日期',date); console.log('一個月中的某一天=',date.getDate()); console.log('一周中的某一天=',date.getDay()); console.log('月份 (0 ~ 11)當(dāng)前的月份=',date.getMonth() + 1); console.log('當(dāng)前的年=',date.getFullYear()); console.log('日期--->字符串',date.toLocaleString());
2.日期格式化
function dateFormat(fmt, date) {
if(!fmt || !date){
console.log('格式化不能為null');
return;
}
const opts = {
"Y+": date.getFullYear().toString(), // 年
"M+": (date.getMonth()+1).toString(), // 月
"d+": date.getDate().toString(), // 日
"H+": date.getHours().toString(), // 時
"m+": date.getMinutes().toString(), //分
"s+": date.getSeconds().toString(), //秒
// 有其他格式化字符需求可以繼續(xù)添加黄刚,必須轉(zhuǎn)化成字符串
};
let ret;
let result = fmt;
for(let key in opts){
const regStr = `(${key})`;
ret = new RegExp(regStr).exec(fmt);
if(ret){
const replaceStr = (ret[1].length == 1) ? (opts[key]) : (opts[key].padStart(ret[1].length, "0"))
result = result.replace(ret[1],replaceStr);
}
}
return result;
}
console.log('格式化---',dateFormat("YYYY-MM-dd HH:mm:ss", new Date()));
4.內(nèi)置對象 - 正則表達式
`正則結(jié)構(gòu): var expression = / pattern / flags ;
flags取值
g: 表示全局(global)模式,即模式將被應(yīng)用于所有字符串民效,而非在發(fā)現(xiàn)第一個匹配項時立即停止憔维;
i: 表示不區(qū)分大小寫(case-insensitive)模式,即在確定匹配項時忽略模式與字符串的大小寫畏邢;
m: 表示多行(multiline)模式业扒,即在到達一行文本末尾時還會繼續(xù)查找下一行中是否存在與模式匹配的項。`
正在表達式說明
() 的作用是提取匹配的字符串舒萎。表達式中有幾個()就會得到幾個相應(yīng)的匹配字符串程储。比如 (\s+) 表示連續(xù)空格的字符串。
[] 是定義匹配的字符范圍。比如 [a-zA-Z0-9] 表示字符文本要匹配英文字符和數(shù)字章鲤。
{} 一般用來表示匹配的長度摊灭,比如 \d{3} 表示匹配三個數(shù)字,\d{1,3} 表示匹配1~3個數(shù)字败徊,\d{3,} 表示匹配3個以上數(shù)字
^ 匹配一個字符串的開頭帚呼,比如 (^a) 就是匹配以字母a開頭的字符串
$ 匹配一個字符串的結(jié)尾,比如 (b$) 就是匹配以字母b結(jié)尾的字符串
^ 還有另個一個作用就是取反,比如[^xyz] 表示匹配的字符串不包含xyz 只有出現(xiàn)在[]中才表示取反
\d 匹配一個非負整數(shù)皱蹦, 等價于 [0-9]
\s 匹配一個空白字符
\w 匹配一個英文字母或數(shù)字煤杀,等價于[0-9a-zA-Z]
. 匹配除換行符以外的任意字符,等價于[^\n]
* 表示匹配前面元素0次或多次沪哺,比如 (\s*) 就是匹配0個或多個空格
+ 表示匹配前面元素1次或多次沈自,比如 (\d+) 就是匹配由至少1個整數(shù)組成的字符串
? 表示匹配前面元素0次或1次,相當(dāng)于{0,1} 凤粗,比如(\w?) 就是匹配最多由1個字母或數(shù)字組成的字符串
4.1.小試牛刀
const regx1 = /\.doc/gim;
const regx2 = new RegExp('\\.00-Doc文檔','gim'); // 對 \. 再次轉(zhuǎn)義
console.log('regx1', regx1.test('dsjfjkds.00-Doc文檔'));
console.log('regx2', regx2.test('dsjfjkds.00-Doc文檔'));
4.2. 匹配的方法
test酥泛、match、replace
console.log('test', /\d+/.test('a123')); // 至少一個數(shù)字
console.log('match', '12fgfd345dsfdf'.match(/\d+/g)); // match是獲取正則匹配到的結(jié)果嫌拣,以數(shù)組的形式返回 ["12", "345"]
console.log('replace','12fgfd345dsfdf'.replace(/\d+/g,'A')); //replace 匹配到了就替換AfgfdAdsfdf
4.3. 常用示例
// 去除字符串空格
String.prototype.customTrim = function () {
return this.replace(/(^\s+)|(\s+$)/gim, '');
};
console.log('dsafdss adfdsa fdsaf'.customTrim());
// 獲取數(shù)據(jù)類型
function getDataType(obj){
let rst = Object.prototype.toString.call(obj);
rst = rst.replace(/\[object\s(\w+)\]/,'$1'); // [object Xxx] $1 是正則表達式中第一個() 中匹配的內(nèi)容柔袁。
return rst.toLowerCase();
}
console.log(this.getDataType(343454));
// 電話號碼轉(zhuǎn)化
function telFormat(tel){
tel = String(tel);
return tel.replace(/(\d{3})(\d{4})(\d{4})/, '$1****$3');
}
console.log(this.telFormat('19876363726'))