JavaScript基礎以及進階知識
JavaScript基礎知識回顧:
目錄:
- 比較運算子
- 多行字串,模板字串
- 嚴格模式
- 函式定義和呼叫
- 變數作用域與解構賦值、NameSpace、塊級作用域let、const
- 方法
- 高階函式
- 閉包
我們一個一個慢慢來:
比較運算子:
-
= 如果1=’1’,則為false
-
== 等於 型別不一樣,值一樣,也會判斷為true
-
=== 絕對等於,型別一樣,值一樣,判斷為true
-
!== 不等於
-
這是js的缺陷,儘量不使用==比較
浮點數問題:
console.log((1/3)===(1-2/3))
結果為false,儘管數值是都等於1/3
儘量避免使用小數計算,因為精度問題
ES6中的模版字串:
在新行中插入的任何字元都是模板字串中的一部分,使用普通字串,你可以通過以下的方式獲得多行字串:
console.log('string text line 1\n' +
'string text line 2');
"string text line 1
string text line 2"
要獲得同樣效果的多行字串,只需使用如下程式碼:
console.log(`string text line 1
string text line 2`);
"string text line 1
string text line 2"
插入表示式:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> var a=10; var b = 20; console.log(`a = ${a},b = ${b}`); </script> </body> </html>
通過上述程式碼可知,需要把表示式${}放入到``中才能正確執行。
詳細說明:MDN
嚴格模式:
嚴格模式對正常的 JavaScript語義做了一些更改。
- 嚴格模式通過丟擲錯誤來消除了一些原有靜默錯誤(undefined)。
- 嚴格模式修復了一些導致 JavaScript引擎難以執行優化的缺陷:有時候,相同的程式碼,嚴格模式可以比非嚴格模式下執行得更快。
- 嚴格模式禁用了在ECMAScript的未來版本中可能會定義的一些語法。
'use strict'; function getAge(){ var y = new Date().getFullYear(); return y - this.birth; } var xiaoming = { name:'小明', birth:2000, age:getAge }; //開不開啟use strick 結果不一樣 var fn = xiaoming.age; console.log(fn());
具體連結:MDN
函式定義和呼叫:
定義函式方式:
定義方式一
絕對值函式
function abs(x){
return x;
}else{
return -x;
}
一旦執行到return代表函式結束,返回結果
定義方法二
var abs = function(x){
return x;
}else{
return -x;
}
function(x){}是一個匿名函式,可以把結果賦值給abs,通過abs就可以呼叫函式
方法一和方法二等價
呼叫函式:
abs(10)
abs(-10)
引數問題:javascript可以傳任何個引數,也可以不傳引數
引數進來是否存在的問題?假設不存在引數,如何丟擲異常?
var abs = function(x){
//手動丟擲異常來判斷
if (typeof x !== 'number') {
throw 'not a number';
}
if (x>=o) {
return x;
}else{
return -x;
}
}
arguments物件:
加入函式的實參沒有寫多個,但使用時傳入了多個引數,使用arguments物件可以把這多個引數用陣列返回,argument物件其實就是傳入的所有引數的陣列。
特性:
1.arguments物件和Function是分不開的。
2.因為arguments這個物件不能顯式建立。
3.arguments物件只有函式開始時才可用。
使用方法:
雖然arguments物件並不是一個數組,但是訪問單個引數的方式與訪問陣列元素的方式相同
例如:
arguments[0],arguments[1],。。。arguments[n];
在js中 不需要明確指出引數名,就能訪問它們,例如:
function test() {
var s = '';
for (var i = 0; i < arguments.length; i++) {
alert(arguments[i]);
s += arguments[i] + ',';
}
return s;
}
test("name", "age");
結果為name,age
rest引數
例如:函式定義了兩個引數,但是傳入了第三個引數,要怎麼取出第三個引數呢?
function test(a,b){
console.log('a->'+a);
console.log('b->'+b);
//以前的方法取第三個元素:
if (arguments.length>2) {
for(var i = 2; i<arguments.length;i++){
console.log(arguments[i])
}
}
}
//現在的方法(rest引數):在函式中定義rest引數
function test1(a,b,...rest){
console.log('a->'+a);
console.log('b->'+b);
console.log(rest);
}
變數的作用域:
變數的作用域:
function a(){
var x = 1;
//內部函式可以訪問外部函式的成員,反之不行
function aa(){
var y = x +1; //2
}
//外部訪問了內部函式的變數,會不行
var z = y+1; //報錯
}
function foo(a,b){
var x = 1;
function bar(){
var x = 'A';
console.log(x);
}
console.log(x);
bar();
}
foo();
結果: 1 A
全域性物件window
'use strict';
window.alert('呼叫Windows.alert');
var old_alert = window.alert;
window.alert = function(){
alert('無法使用alert方法');
}
window.alert = old_alert;
alert('又可以使用alert方法了');
呼叫的結果:只執行了兩次,第一次輸出-->呼叫Windows.alert;第二次輸出-->又可以使用alert方法了
Let關鍵字:
區域性作用域let
ES6let關鍵字,解決區域性作用域衝突問題,現建議大家都用let去定義區域性變數
function aaa() {
for(vari=0;i<100;i++){
console.log(i)
}
console.log(i+1); //問題? i 出了這個作用域還可以使用
}
//使用let後
function aaa() {
for(leti=0;i<100;i++){
console.log(i)
}
console.log(i+1); //Uncaught ReferenceError: i is not defined
}
const關鍵字:
在ES6之後,用const定義常量;
const PI = '3.14';
console.log(PI);
PI = '123'; //報錯,常量不允許修改
名稱空間NameSpace:
防止重名以及命名汙染的現象發生;
var MYAPP = {};
var MYAPP2 = {};
MYAPP.name = 'myapp';
MYAPP.version = '1.0';
MYAPP.foo = function(){
console.log("測試");
};
MYAPP.foo();
MYAPP2.name = 'myapp';
MYAPP2.version = '1.0';
MYAPP2.foo = function(){
console.log("測試2");
};
MYAPP2.foo();
方法:
定義方法
方法就是把函式放在物件的裡面,物件只有兩個東西:屬性和方法
var xiaoming = {
name:'小明',
birth:2000,
age:function(){
var y = new Date().getFullYear();
return y -this.birth;
}
};
console.log(xiaoming.age());
成員屬性只對子方法負責,不對孫方法負責。
var xiaoming = {
name:'小明',
birth:2000,
age:function (){
//儲存xiaoming這個物件
var that = this;
function getAgeFromBirth(){
var y = new Date().getFullYear();
//如果不儲存,這裡是找不到birth屬性的
return y - that.birth;
}
return getAgeFromBirth();
}
}
console.log(xiaoming.age());
為了解決上面這個缺陷:我們引入了apply關鍵字;
apply方法是可以控制this指向的,該方法有兩個引數,第一個是getArg要使用的是那個物件,第二個是陣列;
//解決的js的缺陷
function getAge(){
var y = new Date().getFullYear();
return y - this.birth;
}
var xiaoming = {
name:'小明',
birth:2000,
age :getAge
};
//apply(x,y);
//第一個引數是getAge中this的所需要的指向(不指向為null)
//第二個引數預設是陣列格式,表示傳入的引數型別
console.log(getAge.apply(xiaoming,[]));
高階函式使用:
map、reduce、filter
map:實現每個數平方
function pow(x){
return x * x;
}
var arr = [1,2,3,4,5,6,7,8,9];
var result = arr.map(pow);
console.log('='+result);
reduce:實現累加
var arr = [1,2,3,4,5];
//1+2-->3 x
//x+4-->7 x
//x+5-->12 x
var result = arr.reduce(function(x,y){
return x+y;
});
console.log(result);
filter:過濾掉不符合函式要求的值
var arr = [1,2,3,4,5,6,7];
var r = arr.filter(function(x){
return x%2 !== 0;
});
console.log(r);
閉包:
閉包的引入:
//函式內部可以訪問全域性變數
var n = 999;
function f1(){
console.log(n);
}
//外部訪問不了函式內部的變數
function f1(){
var n = 999;
}
console.log(n);
使用閉包來實現外部引用內部資訊:
function f1(){
var n = 999;
function f2(){
console.log(n);
}
return f2;
}
var res = f1();
res();
複雜閉包的實現:
//閉包複雜程式碼段
function createIncermentor(start){
return function(){
return start++;
};
}
var inc = createIncermentor(10);
console.log(inc());
console.log(inc());
console.log(inc());
結果:10 11 12
定義類:
function Person(){
var _age;
function setAge(n){
_age = n;
}
function getAge(){
return _age;
}
//{} //var obj = {}是物件
return {
name:name,
getAge:getAge,
setAge:setAge
};
}
var p1 = Person("xbhog");
p1.setAge(88);
console.log(p1.getAge());
結果:88
感覺可以的朋友,可以給我點點關注或者推薦,感謝!