基礎
邏輯運算符
|| && !
1、||
或,只要任意一個成立就返回true
2、 &&
與,只要兩個同時成立才返回true,任一一個不成立,就返回false
3、!
非 返回相反的值
賦值運算
n ++; 相當於 n = n+1
n += int;加等於
n -= int; 減等於
n *= int;乘等於
n /= int;除等於
循環
for循環
var s1 = [1,2,3,4,'da','df','2'];
for (var i=0;i<s1.length;i++){
console.log(i);
console.log(s1[i])
};
while 循環
var a = 10;
while (a <= 13){console.log("小於13",a);a++;console.log("等於13")}
三元運算
var a = 10;
var b = 20;
var c = a > b ? a : b #如果a>b,那麼取a的值,反正取b的值
判斷
a = 10;
if (a>5){
console.log('yes');
} else {
console.log('no');
}
var a = 10;
if (a > 5){
console.log("a > 5");
}else if (a < 5) {
console.log("a < 5");
}else {
console.log("a = 5");
}
switch 循環
var day = new Date().getDay();
switch (day) {
case 0:
console.log("Sunday");
break;
case 1:
console.log("Monday");
break;
default:
console.log("...")
}
正則
創建一個匹配5-11位的以字母開頭的正則
var reg1 = new RegExp("^[a-zA-Z][a-zA-Z0-9_]{5,11}$");
var s1 = 'hello!';
var s2 = 'hao'
console.log(reg1.test(s1)); // 結果true
console.log(reg1.test(s2)); // 結果false
如果方便簡潔的話,還可以這樣寫。
console.log(/^[a-zA-Z][a-zA-Z0-9_]{5,11}$/.test('hello'));
console.log(/^[a-zA-Z][a-zA-Z0-9_]{5,11}$/.test('')); //結果爲true
console.log(/^[0-9][a-zA-Z0-9_]{5,11}$/.test('')); //結果爲false,因爲undefiend數字開頭
console.log(/^[a-zA-Z][a-zA-Z0-9_]{5,11}$/.test('undefiend')); //結果爲true
因爲不填寫參數,默認會加一個undefiend,js會默認轉換爲undefiend字符串
替換
var s1 = 'Dasdadasd';
var s2 = s1.replace(/d/,'你好'); //g 全局替換,i忽略大小寫
console.log(s2);
結果:Das你好adasd
var s1 = 'Dasdadasd';
var s2= s1.replace(/d/gi,'你好'); //g 全局替換,i忽略大小寫
console.log(s2);
結果:你好as你好a你好as你好
正則坑:
1、表達式內一定不要有空格,否則無法識別。
2、如果正則匹配不傳參數,會默認傳一個undefiend
,但是js會把undefiend
當做一個字符串去匹配,因此匹配不到
3、正則表達式完成替換,不是替換原來的字符串,而是生成新的字符串,無法單純替換原來的字符串~
函數
# 函數的定義
普通函數
function foo(a,b){
console.log(a);
console.log(b)
}
#函數的調用
foo(1,2)
# 定義帶返回值的函數,加一個return即可
function foo(a,b){
return a+b
}
# 調用有返回值的函數,只需要var 一個變量賦值接收這個返回值即可
var ret= foo(1,2)
console.log(ret)
結果爲3
# 匿名函數,沒有名稱的函數
function (a,b){
console.log(a);
console.log(b);
return a+b
}
這種情況下,匿名函數無法調用,如果需要調用,需要var一個變量進行賦值即可
var func = function (a,b) {
console.log(a);
console.log(b);
return a+b
}
如果調用,直接運行func即可
func(a,b)
# 立即執行函數
(function (a,b){
console.log(a);
console.log(b);
var abc = "我是函數內部的變量,其他地方無法調用,只在函數內部生效"
}) (1,2);
a和b爲形參
1和2位實參
# 爲什麼需要立即執行函數
有些方法或者變量,只需要調用一次即可,因此寫一個立即執行函數,
假如有一個變量定義在立即執行函數中,其他的地方無法訪問這個變量的,
這樣就做到了隔離其他的調用、上面的例子abc,就無法在其他地方調用。
假如函數需要傳2個參數。但是隻傳遞了一個參數,那麼那個沒有進行傳遞的參數默認會是 undefined
假如函數需要傳遞2個參數,但是傳遞了5個參數,這個函數是不會報錯的
舉例:
var abc = func (a,b){
console.log("a的值爲:",a);
console.log("b的值爲:",b);
}
abc(1)
打印的結果爲
a的值爲:1
b的值爲:undefined
var abc = function(a,b,c) {
console.log(arguments);
console.log(arguments.length);
}
# 執行
abc(1,2,3)
console.log(arguments) 可以打印參數的結果
# 實現一個加法運算
function add(a,b,c) {
console.log(arguments); //打印參數的鍵值
console.log(arguments.length); //打印參數的長度
var ret = 0; //定義一個參數
for (var i=0;i<arguments.length;i++){
ret += arguments[i]; // 把ret+arguments[i]的結果繼續賦值給ret,以此循環
}
return ret; //返回結果
}
console.log(add(1,2,3,4)); //不管多少參數,都不會報錯。
結果爲 10
作用域
函數作用域就近原則
var city = "上海";
function func(){
var citt = "北京";
function inner(){
var city = "深圳";
console.log(city);
}
inner();
}
調用
func() // 結果打印是 深圳
因爲就近原則
var city = "BeiJing";
function Bar() {
console.log(city);
}
function f() {
var city = "ShangHai";
return Bar;
}
var ret = f();
ret(); // 打印結果是?
打印結果應該爲Beijing
因爲上面那個函數靠近上面定義的beijing,因此打印結果爲北京
//調用函數的時候,要往回找函數的定義階段,
//如果函數定義階段沒有數據,就去找全局變量
//首先直接f(),沒有打印,return調用bar函數,bar函數內沒有定義city,因此需要去全局變量中找
//如果全局變量沒有,則返回undefined
閉包
var city = "BeiJing";
function f(){
var city = "ShangHai";
function inner(){
console.log(city);
}
return inner;
}
var ret = f();
ret();
//執行結果爲 ShangHai
// 調用 f(), 其實是執行的inner這個函數,因此f()函數return返回的是inner這個函數
//inner函數沒有定義city這個變量
//因此需要去inner外面去找,靠近inner,定義了一個city = "ShangHai" 因此輸出結果爲ShangHai
//如果函數內部沒有定義city,那麼就去全局變量中查找
js詞法分析
js執行函數的過程會先進行分析
當函數調用的前一瞬間,會先形成一個激活對象:Avtive Object(AO),並會分析以下3個方面:
1:函數參數,如果有,則將此參數賦值給AO,且值爲undefined。如果沒有,則不做任何操作。
2:函數局部變量,如果AO上有同名的值,則不做任何操作。如果沒有,則將此變量賦值給AO,並且值爲undefined。
3:函數聲明,如果AO上有,則會將AO上的對象覆蓋。如果沒有,則不做任何操作。
函數內部無論是使用參數還是使用局部變量都到AO上找。
var age = 18;
function foo(){
console.log(age); //函數經過分析,返現age開始沒有定義,生成一個undefined,於是不糊賦值,哪怕全局變量有定義age
var age = 22; //第一步,因爲沒有函數調用age,會生成一個AO.age = undefined
console.log(age); //這裏就執行了age
}
foo(); // 問:執行foo()之後的結果是?
// 結果是先打印 undefined 後打印22
// 先詞法分析,後賦值,先分析 var,之後再進行賦值操作,如果var age ,後面有 function age進行調用,那麼會被覆蓋
// 總結就是先分析函數內部變量定義過程,先看參數,後看局部變量,最後看有沒有函數定義,後執行
var age = 18;
function foo(){
console.log(age);
var age = 22;
console.log(age);
function age(){ // 這裏有函數調用age,不會生成undefined,
console.log("呵呵");
}
console.log(age);
}
foo(); // 執行後的結果是?
//先分析 AO賦值
//第一個console.log(age); 一開始沒有定義,則爲undefined,後面var age = 22;定義了,則爲AO.age = undefined,之後 function age()覆蓋了第二步的 AO.age = undefined,變成了 AO.age = function(){}
//於是第一個age變成了 AO.age = function(){},第二個賦值了變成了22,第三個變成了 呵呵
第一個打印的,永遠是分析階段最後一個狀態,或者爲undefined 或者爲函數,第二步才真正執行。
參考
詞法分析過程:
1、分析參數,有一個參數,形成一個 AO.age=undefine;
2、分析變量聲明,有一個 var age, 發現 AO 上面已經有一個 AO.age,因此不做任何處理
3、分析函數聲明,有一個 function age(){...} 聲明, 則把原有的 age 覆蓋成 AO.age=function(){...};
最終,AO上的屬性只有一個age,並且值爲一個函數聲明
執行過程:
注意:執行過程中所有的值都是從AO對象上去尋找
1、執行第一個 console.log(age) 時,此時的 AO.age 是一個函數,所以第一個輸出的一個函數
2、這句 var age=22; 是對 AO.age 的屬性賦值, 此時AO.age=22 ,所以在第二個輸出的是 2
3、同理第三個輸出的還是22, 因爲中間再沒有改變age值的語句了
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
李文周
https://www.cnblogs.com/liwenzhou/p/8004649.html
小技巧:
f12,在console界面輸入
document.body.contentEditable=true
ctrl +shift +p 彈出瀏覽器的輸入框
可以截取瀏覽器內的屏幕截圖
即可修改頁面信息