這是我在學習中的一些筆記總結,包括閉包、做用域、原型等等常考熱點,這些將以面試題的方式呈現給你們,全文分爲 JS 基礎、JS 高級、jQuery 和 vue 四部分,認真讀完而且敲幾遍代碼,您定會受益不淺,同時但願你們批評指正。
1. 涉及面試題:什麼是閉包?
閉包的定義其實很簡單:函數 A 內部有一個函數 B,函數 B 能夠訪問到函數 A 中的變量,那麼函數 B 就是閉包。javascript
function A(){ let a=1; window.B=function(){ console.log(a) } } A(); B();//1複製代碼
不少人對於閉包的解釋多是函數嵌套了函數,而後返回一個函數。其實這個解釋是不完整的,就好比我上面這個例子就能夠反駁這個觀點。css
在 JS 中,閉包存在的意義就是讓咱們能夠間接訪問函數內部的變量。html
2. 經典面試題:循環中使用閉包解決`var `定義函數的問題;
for(var i=0;i<=5;i++){ setTimeout(function timer(){ console.log(i) },i*1000) } console.log(i)複製代碼
輸出結果:當即輸出一個6,而後每隔一秒輸出一個6;前端
首先由於 setTimeout
是個異步函數,因此會先把循環所有執行完畢,這時候 i
就是 6 了,因此會輸出一堆 6。vue
解決辦法有3種,java
第一種是利用閉包的方式:程序員
for(var i=0;i<=5;i++){ (function(j){ setTimeout(function timer(){ console.log(j) },j*1000) })(i) }複製代碼
在上述代碼中,咱們首先使用了當即執行函數將 i
傳入函數內部,這個時候值就被固定在了參數 j
上面不會改變,當下次執行 timer
這個閉包的時候,就能夠使用外部函數的變量 j
,從而達到目的。es6
第二種就是使用 setTimeout
的第三個參數,這個參數會被當成 timer
函數的參數傳入。面試
for(var i=0;i<=5;i++){ setTimeout((j) => { console.log(j); },i*1000,i) }複製代碼
setTimeout
還容許更多的參數。它們將依次傳入推遲執行的函數(回調函數)。ajax
setTimeout((a,b,c) => { console.log(a,b,c) }, 2000, "my", "name", "is starsion"); //my name is starsion複製代碼
更多關於setTimeOut的用法,請參考阮一峯老師的 異步操做 之 定時器
第三種就是使用 let
定義 i
了來解決問題了,這個也是最爲推薦的方式
for(let i=0;i<=5;i++){ setTimeout(() => { console.log(i) },i*1000) }複製代碼
更多關於let和var的區別,請參考阮一峯老師的 let命令
ES6 以前 JS 沒有塊級做⽤域。例如
if (true) { var name = 'zhangsan' } console.log(name)複製代碼
從上⾯的例⼦能夠體會到做⽤域的概念,做⽤域就是⼀個獨⽴的地盤,讓變量不會外泄、暴露出去。 上⾯的 name 就被暴露出去了,所以,JS 沒有塊級做⽤域,只有全局做⽤域和函數做⽤域。
可是 ES6 中開始加⼊了塊級做⽤域,使⽤ let 定義變量便可
if (true) { let name1 = 'zhangsan' } console.log(name1) // 報錯,由於let定義的name是在if這個塊級做⽤域複製代碼
1. js做用域(全局做用域 和 函數做用域)內部能夠訪問外部,但外部的不能訪問內部的
var a=10; function aaa(){ alert(a); }; aaa();//10複製代碼
function aaa(){ var a=10; }; aaa(); console.log(a)//Uncaught ReferenceError: a is not defined複製代碼
var a=10; function aaa(){ console.log(a);//10 }; function bbb(){ var a=20; aaa(); } bbb();//10複製代碼
function aaa(){ a=10; } aaa(); function aaa(){ var a=b=10; } aaa(); console.log(b)//10 console.log(a)//Uncaught ReferenceError: a is not defined複製代碼
2. 不用var 定義變量時,會默認爲是全局變量(不規範,不推薦)
function aaa(){ a=10; } aaa(); function aaa(){ var a=b=10; } aaa(); console.log(b) console.log(a)複製代碼
3. 變量的查找是就近原則去尋找,定義的var變量;
變量的聲明被提早到做用域頂部,賦值保留在原地,以下 domo ;
function aaa(){ console.log(a);//undefined var a=20; } aaa(); 複製代碼
var a=10; function aaa(){ console.log(a);//undefined var a=20; } aaa();複製代碼
var a=10; function aaa(a){ console.log(a);//10 var a=20; //由於 a 是形參,優先級高於 var a; 因此 局部變量a的聲明其實被忽略了。 } aaa(a);複製代碼
⾸先認識⼀下什麼叫作 ⾃由變量 。以下代碼中, console.log(a)
要獲得 a
變量,可是在當前的做 ⽤域中沒有定義 a
(可對⽐⼀下 b
)。當前做⽤域沒有定義的變量,這成爲 ⾃由變量 。⾃由變量如 何獲得 —— 向⽗級做⽤域尋找。
var a = 100; function fn() { var b = 200; console.log(a); console.log(b); }; fn();複製代碼
若是⽗級也沒呢?再⼀層⼀層向上尋找,直到找到全局做⽤域仍是沒找到,就宣佈放棄。這種⼀層⼀ 層的關係,就是 做⽤域鏈 。
var a = 100; function F1() { var b = 200; function F2() { var c = 300; console.log(a) // ⾃由變量,順做⽤域鏈向⽗做⽤域找 console.log(b) // ⾃由變量,順做⽤域鏈向⽗做⽤域找 console.log(c) // 本做⽤域的變量 }; F2(); }; F1();複製代碼
1. 判斷輸出結果,而且解釋緣由?
var a = 1; (function a () { a = 2; console.log(a); })(); // 輸出結果 ƒ a () { a = 2; console.log(a); }複製代碼
這道題,猛地一看,不少人都會以爲,console.log(a) 的值爲 2,其實否則,
當即調用的函數表達式(IIFE) 有一個 本身獨立的 做用域,若是函數名稱與內部變量名稱衝突,就會永遠執行函數自己;因此上面的結果輸出是函數自己;
若是將函數名字改一下,好比改成 x
var a = 1; (function x () { a = 2; console.log(a); })(); // 2複製代碼
函數表達式中的函數名稱,只有本身獨立的做用域能夠拿到,不會影響全局
var a = 1; (function a () { a = 2; console.log(window.a); })(); // 1複製代碼
var a = 1; (function x () { a = 2; console.log(a); })(); // 2複製代碼
【考點:函數arguments】
在函數代碼中,使用特殊對象 arguments,開發者無需明確指出參數名,就能訪問它們。
例如,在函數 sayHi() 中,第一個參數是 message。用 arguments[0] 也能夠訪問這個值,即第一個參數的值(第一個參數位於位置 0,第二個參數位於位置 1,依此類推)。
所以,無需明確命名參數,就能夠重寫函數:
function sayHi() { if (arguments[0] == "bye") { return; } alert(arguments[0]); }複製代碼
【考點:數據類型】
var num; num=5+true; A、true B、false C、5 D、6複製代碼
解析:true 的值爲1,false 的值爲0;以下代碼
console.log(true==1)//true console.log(true===1)//false console.log(false==0)//true console.log(false===0)//false複製代碼
var x=prompt("請輸入1-5的數字",""); switch (x) { case 「1」:alert(「one」); case 「2」:alert(「two」); case 「3」:alert(「three」); case 「4」:alert(「four」); case 「5」:alert(「five」); default:alert(「none」); }複製代碼
運行以上程序,在提示對話框中輸入「4」,依次彈出的對話框將輸出: ( B )
A、four,none B、four,five,none C、five D、five,none複製代碼
解析:由於執行完以後,沒有加break,會一直往下執行代碼。
輸出結果是(B).(選擇一項) 【考點:for循環】
a=new Array(2,3,4,5,6); sum=0; for(i=1;i<a.length;i++ ) sum +=a[i]; document.write(sum); A. 20 B. 18 C. 14 D. 12複製代碼
注意:i 是從 1 開始循環的,不要掉到坑裏。
【考點:location對象】
A. hostname B. Port C. pathname D. href複製代碼
解析:Location
對象提供如下屬性。
Location.href
:整個 URL。Location.protocol
:當前 URL 的協議,包括冒號(:
)。Location.host
:主機,包括冒號(:
)和端口(默認的80端口和443端口會省略)。Location.hostname
:主機名,不包括端口。Location.port
:端口號。Location.pathname
:URL 的路徑部分,從根路徑/
開始。Location.search
:查詢字符串部分,從問號?
開始。Location.hash
:片斷字符串部分,從#
開始。Location.username
:域名前面的用戶名。Location.password
:域名前面的密碼。Location.origin
:URL 的協議、主機名和端口。更多關於 location對象的知識,請點擊查看。
x=11; y="number"; m= x+y ; m的值爲(A) A. 11number B. number C. 11 D. 程序報錯複製代碼
這段代碼的意思是(D)
A. 等待1000秒後,再彈出一個對話框
B. 等待1秒鐘後彈出一個對話框
C. 語句報錯,語法有問題
D. 每隔一秒鐘彈出一個對話框複製代碼
var a=15.49;
document.write(Math.round(a));
輸出的結果是(A)
A. 15 B. 16 C. 15.5 D. 15.4複製代碼
解析:Math.ceil()
執行向上舍入
Math.floor()
執行向下舍入
Math.round()
執行標準舍入(四捨五入)
【考點:parseInt取整】
var a = 1.5,b;
b=parseInt(a);
A. 2 B. 0.5 C. 1 D. 1.5複製代碼
解析:parseInt()函數將字符串轉化爲整數,他從字符串的開頭開始解析,在第一個非整數位中止解析,而且返回前面讀到的全部整數,若是字符串不以整數開頭,將返回NaN(Not a Number:非數字值)。
點擊查看 parseInt() 用法
【考點:substr() 截取字符串的使用,isNaN 判斷是否爲數字】
var str= form1.fname.value; if(str.substr(0,4)!="010-" ||str.substr(4).length!=8 || isNaN(parseFloat(str.substr(4)))) alert("無效的電話號碼!");複製代碼
解析:
substr(m,n) 截取一段字符,兩個參數m,n,表示從m位開始(不包括m),向後邊截取n位;若是隻寫一個參數m,會從這個參數後邊所有截取;
isNaN判斷是否NaN(不是數字),若是該字符裏不是全數字,則返回true;若是是全數字,則返回false。
【考點:javascript保留字,防止命名出現使用保留字而產生錯誤】
A.with B.parent C.class D.void複製代碼
關鍵字26 breakcase catch continue debugger default delete doelsefinally for function if in instance new return switch this throw try typeofvar voidwhile with 保留字 abstract boolean bytechar class const double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile複製代碼
在JavaScript引擎中使用關鍵字作標識符會致使"Identifier Expected"錯誤
【考點:對null,undefined,NaN的理解】
A.null instanceof Object //false B.null === undefined //false C.null == undefined //true D.NaN == NaN //false複製代碼
解析:點擊查看 NaN的運算規則 null和undefined
【考點:邏輯運算符和位運算符】
1.A、&& B、|| C、^ D、!複製代碼
解析:布爾運算符用於將表達式轉爲布爾值,一共包含四個運算符。前三個稱爲邏輯運算符
!
&&
||
?:
點擊查看更多 關於運算符的知識
【考點:變量定義規則】
A、 eee B、 _abc C、box_1 D、 2point複製代碼
解析:
駝峯式命名法:又叫小駝峯式命名法。通常用來命名變量,用來解釋描述變量
例如:var planeBulletSpeed; //飛機子彈的速度
【考點:四則運算】
A.-15 B、10 C、-5 D、5複製代碼
【考點:邏輯運算】點擊查看 邏輯運算符
A、1<2 && "5" !=5 //false B、2>2*1 || "5" ==5 //true C、2>2*1 && 5 ==5 //false D、1<2 && "5" ==5 //true複製代碼
【考點:while循環,避免出現死循環,除非有須要】
var x=-1; do{ x=x*x; } while(!x); A、是死循環 B、循環執行二次 C、循環執行一次 D、有語法錯誤複製代碼
解析:!1 的值爲false,就是說知足循環體知足 爲false 的是時候的執行代碼塊
【考點:for循環,何時跳出循環】
A、9 B、10 C、11 D、不定複製代碼
解析:
for(var i=1;i++<10;){ console.log(i)} console.log(i)//11 // 2 3 4 5 6 7 8 9 10 11複製代碼
【考點:鍵盤事件】
A、keydown B、keyover C、keypress D、keyup複製代碼
鍵盤事件由用戶擊打鍵盤觸發,主要有keydown
、keypress
、keyup
三個事件,它們都繼承了KeyboardEvent
接口。
【考點:四則運算和邏輯運算綜合應用】
var a=3;
a+=8*2;
alert(a>10&&a<=20);複製代碼
A;string B:undefined C:Object D:String複製代碼
【考點:JavaScript語言特性】C
A.Javascript是一種腳本語言
B.Javascript是事件驅動的
C.Javascript代碼須要編譯之後才能執行
D.Javascript是獨立於平臺的複製代碼
解析:JavaScript是一門腳本語言。弱數據類型,基於對象,基於事件驅動的語言。
【考點:函數調用】B
function f(y) { var x=y*y; return x; } for(x=0;x<5;x++) { y=f(x); document.writeln(y); } A.0 1 2 3 4 B.0 1 4 9 16 C.0 1 4 9 16 25 D.以上答案都不對複製代碼
【考點:數組的理解,包括建立,長度,元素的類型等概念】
A.數組的長度必須在建立時給定,以後便不能改變
B.因爲數組是對象,所以建立數組須要使用new運算符
C.數組內元素的類型能夠不一樣
D.數組能夠在聲明的同時進行初始化複製代碼
【考點:toFixed 保留小數位數的使用】
var n = new Number(3456);
alert(n.toFixed(2));
如下選項正確的是:(C)
A.輸出34 B.輸出 56 C.輸出3456.00 D.輸出345600複製代碼
【考點:注意:若是 end 未被規定,那麼 slice() 方法會選取從 start 到數組結尾的全部元素】
var str = 「32px」;
var str1 = str.slice(-2);
alert(str);
alert(str1);
A依次輸出」px」 「px」
B依次輸出」32」 「32」
C依次輸出」32px」 「px」
D依次輸出」32px」 「32px」複製代碼
解析:slice
方法用於提取目標數組的一部分,返回一個新數組,原數組不變。
arr.slice(start, end);複製代碼
-2
表示倒數計算的第二個位置,-1
表示倒數計算的第一個位置。
點擊查看更多關於 數組slice方法 的知識。
【考點:字符串的方法indexof的使用,之一返回的是下標】:
var str = 「12px」;
var s = str.indexof(「2」);
alert(s);
A.輸出1 B.輸出 2 C.輸出 p D.輸出 12複製代碼
【考點:setTimeout 的使用,注意時間的表達,以毫秒計,1秒應寫爲1000毫秒】
A.window.setTimeout(1000,expression);
B.window.setTimeout(expression,1);
C.window.setTimeout(1,expression);
D.window.setTimeout(expression,1000);複製代碼
點擊查看更多關於 setTimeOut 的用法
【考點:方法的調用,通常若是沒有明確對用者,則是window對象】
A.document B.Window C.form D.Location複製代碼
【考點:history對象使用】
A.back(-1) B.back(1) C.forward(1) D.go(-1)複製代碼
解析:window.history
屬性指向 History 對象,它表示當前窗口的瀏覽歷史。
// 後退到前一個網址
history.back()
// 等同於
history.go(-1)複製代碼
點擊查看更多關於 history 的知識。
A.x<10 B.x<=10 C.x<20 D.x<=20複製代碼
【考點:while循環】
A.Math.floor(Math.random()*6)
B.Math.floor(Math.random()*7)
C.Math.floor(Math.random()*8)
D.Math.ceil(Math.random()*8)複製代碼
【考點:隨機數產生,注意左包右不包,隨機很多天後會常常用到,需熟練掌握】
【考點:鍵盤事件,獲取按鍵編碼 event.keyCode】
<input name=」password」 type=」text」 onkeydown="myKeyDown()"> A. function myKeyDown(){ if (window.keyCode==13) alert(「你按下了回車鍵」); B. function myKeyDown(){ if (document.keyCode==13) alert(「你按下了回車鍵」); C. function myKeyDown(){ if (event.keyCode==13) alert(「你按下了回車鍵」); D. function myKeyDown(){ if (keyCode==13) alert("你按下了回車鍵") 複製代碼
A.onFocus B.onBlur C.onSubmit D.onKeyDown複製代碼
var x,y;
x=10;
y=x++;
運行以上程序後,變量y的值爲 10 。複製代碼
解析:自增和自減運算符有一個須要注意的地方,就是放在變量以後,會先返回變量操做前的值,再進行自增/自減操做;放在變量以前,會先進行自增/自減操做,再返回變量操做後的值。
var i,j;
i=0;
j=i&&(++i);
運行以上程序後,變量i的值爲0 。複製代碼
解析:
console.log(0&&1)//0複製代碼
var i; i=8; do{ i++; } while(i>100); 運行以上程序後,變量i的值爲9。複製代碼
for(var i=1;i<=10;i++){ if(i==5) continue; if(i==8) break; alert(i); } 運行以上程序後,彈出的對話框依次輸出的值爲 1,2,3,4,6,7 。複製代碼
解析:continue 是接着執行,可是不執行下邊的語句了。
【考點:程序邏輯,簡單的算法實現功能,一題多解】
function unique1(array){ var n=[]; //一個新的臨時數組 //遍歷當前數組 for(var i=0;i<array.length;i++){ //若是當前數組的第i已經保存進了臨時數組,那麼跳過, 不然把當前項push到臨時數組裏面 if(n.indexOf(array[i])==-1) n.push(array[i]); } return n; }複製代碼
var k; for(var i=0;i<5;i++){ for (var j=0;j<10 ;j++){ k=i+j; } } alert(k) //13 【考點:for循環,注意什麼時候跳出循環】複製代碼
解析:i=5 時跳出循環,此時k=4+9=13。
var a=0; test(); function test(){ var a = 6 b() } function b(){ alert(a) } 結果爲: 0 【考點:變量的做用域,此處容易出錯】複製代碼
解析:在 test() 調用函數 b 的時候,b內的 alert(a),此時a的做用域爲全局做用域,a=0。
function foo(){ alert("aaaa"); a = setTimeout(foo,100); } foo(); 無限循環調用複製代碼
【考點:setTimeout,以及遞歸調用】
A、confirm() B、alert() C、prompt() D、open()複製代碼
解析:confirm(「提示信息」)
:出現一個確認框(提示信息、確認按鈕、取消按鈕);
prompt(「提示信息」)
:出現一個輸入框,提示用戶輸入信息的,開發時不用;
window.alert(「提示信息」)
:使用窗口的提示框功能輸出提示信息。
注: a) alert
阻塞以後的代碼執行。 b) window
能夠省略。c) alert
中提示信息的換行
【考點:BOM 中open()方法】
A、window.open(「abc.html」,「」,「」);
B、window.open(「」,「abc.html」,「」);
C、window.open(「」,「」,「abc.html」);
D、window.open(「」,「」,「」);複製代碼
解析:window.open
方法用於新建另外一個瀏覽器窗口,相似於瀏覽器菜單的新建窗口選項。它會返回新窗口的引用,若是沒法新建窗口,則返回null
。open
方法一共能夠接受三個參數。
window.open(url, windowName, [windowFeatures])複製代碼
url
:字符串,表示新窗口的網址。若是省略,默認網址就是about:blank
。windowName
:字符串,表示新窗口的名字。若是該名字的窗口已經存在,則佔用該窗口,再也不新建窗口。若是省略,就默認使用_blank
,表示新建一個沒有名字的窗口。另外還有幾個預設值,_self
表示當前窗口,_top
表示頂層窗口,_parent
表示上一層窗口。windowFeatures
:字符串,內容爲逗號分隔的鍵值對(詳見下文),表示新窗口的參數,好比有沒有提示欄、工具條等等。若是省略,則默認打開一個完整 UI 的新窗口。若是新建的是一個已經存在的窗口,則該參數不起做用,瀏覽器沿用之前窗口的參數。更多關於 window.open 的用法請點擊查看;
A、//註釋內容 B、/*註釋內容*/
C、/註釋內容 D、/*註釋內容複製代碼
A、4Myvariable B、My@variable C、function D、Myvariable4複製代碼
解析:
駝峯式命名法:又叫小駝峯式命名法。通常用來命名變量,用來解釋描述變量
例如:var planeBulletSpeed; //飛機子彈的速度
var foo = 1; function(){ console.log(foo); var foo = 2; console.log(foo); } 答案:輸出 undefined 和 2。複製代碼
var x = 1; var y = 0; var z = 0; function add(n){ n=n+1; } y = add(x); function add(n){ n=n+3; } z = add(x);複製代碼
解析:首先,有兩個同名函數,後邊的函數會覆蓋掉前面的函數,其次,一個函數沒有返回值的狀況下,執行完輸出的結果都是 undefined
function DateDemo(){ var d, s="今天日期是:"; d = new Date(); s += d.getMonth() +1 +"/"; s += d.getDate() + "/"; s += d.getFullYear(); return s; } console.log( DateDemo() ) 結果:今天日期是:當前系統日期複製代碼
for(i=0, j=0; i<10, j<6; i++, j++){ k = i + j; }複製代碼
結果:10(當心陷阱)
var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
第一種方法:
arr.toString().split(",").sort((a,b) => { return a - b}).map(Number)複製代碼
第二種方法:
Array.prototype.flat= function() { return [].concat(...this.map(item => (Array.isArray(item) ? item.flat() : [item]))); } Array.prototype.unique = function() { return [...new Set(this)] } const sort = (a, b) => a - b; console.log(arr.flat().unique().sort(sort));複製代碼
第三種方法:
function spreadArr(arr=[]){ if(arr.some(ele=>Array.isArray(ele))){ let newArr = []; arr.forEach((ele) => { if(Array.isArray(ele)){ newArr = newArr.concat(...ele) }else{ if(!newArr.includes(ele)) newArr.push(ele) } }) return spreadArr(newArr); } return arr.sort((a,b)=> a-b); } spreadArr([ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]);複製代碼
第四種方法:
var arr = [2, -5, 6, [6, -5, [2, 5], [8, 10, [6, 8], -3], 2], 5]; function f (arr) { var newarr = []; function fn (arr) { for (var i = 0; i < arr.length; i++) { if (arr[i].length) { if (Array.isArray(arr[i])) { //加這步斷定的目的是,判斷這個元素是否爲數組 fn(arr[i]); } else { newarr.push(arr[i]); }else{ newarr.push(arr[i]); } } } fn(arr); return newarr; } var x = f(arr); var newarr = []; for(var n = 0;n < x.length; n++) { if (newarr.indexOf(x[n]) == -1) { newarr.push(x[n]); } } newarr.sort((a, b) => a - b) console.log(newarr)複製代碼
1. 不要在同一行聲明多個變量。
2. 請使用 ===/!==來比較true/false或者數值
3. 使用對象字面量替代new Array這種形式
4.不要使用全局函數。
5. Switch語句必須帶有default分支
6. 函數不該該有時候有返回值,有時候沒有返回值。
7. For循環必須使用大括號
8. If語句必須使用大括號
9. for-in循環中的變量 應該使用var關鍵字明確限定做用域,從而避免做用域污染。
基本類型: undefined,boolean,number,string,null,symbol(ES6)
引用類型:object,arrary,date,RegExp(正則),Function
基本數據類型是簡單的數據段。
引用類型是由多個值構成的對象,其實都是Object的實例。
基本類型能夠直接訪問,而引用類型的訪問是按照對象在內存中的地址,再按照地址去獲取對象的值,叫作引用訪問。
當從一個變量向另外一個變量賦值引用類型的值時,一樣也會將存儲在變量中的對象的值複製一份放到爲新變量分配的空間中。前面講引用類型的時候提到,
保存在變量中的是對象在堆內存中的地址,因此,與簡單賦值不一樣,這個值的副本其實是一個指針,而這個指針指向存儲在堆內存的一個對象。那麼賦值操做後,
兩個變量都保存了同一個對象地址,則這兩個變量指向了同一個對象。所以,改變其中任何一個變量,都會相互影響,從而引起了對象的深拷貝和淺拷貝的問題。
能夠延伸問一下如何深拷貝。
var 聲明的變量會掛載在 window 上,而 let 和 const 聲明的變量不會:
var 聲明變量存在變量提高,let 和 const 不存在變量提高
let 和 const 聲明造成塊做用域
同一做用域下 let 和 const 不能聲明同名變量,而 var 能夠
Const 一、一旦聲明必須賦值,不能使用 null 佔位。二、聲明後不能再修改 三、若是聲明的是複合類型數據,能夠修改其屬性
根據 JavaScript 中的 變量類型 傳遞⽅式,分爲 值類型(原始類型) 和 引⽤類型 ,值類型變量包括 Boolean、 Null、Undefined、Number、String,引⽤類型包括了 Object 類的全部,如 Date、Array、 Function 等。在參數傳遞⽅式上,值類型是按值傳遞,引⽤類型是按共享傳遞。
在 JS 中,存在着 6 種原始值,分別是:
⾸先原始類型存儲的都是值,是沒有函數能夠調⽤的,⽐如 undefined.toString()
此時你確定會有疑問,這不對呀,明明 '1'.toString() 是能夠使 ⽤的。其實在這種狀況下,'1' 已經不是原始類型了,⽽是被強制 轉換成了 String 類型也就是對象類型,因此能夠調⽤ toString 函數。
除了會在必要的狀況下強轉類型之外,原始類型還有⼀些坑
其中 JS 的 number 類型是浮點類型的,在使⽤中會遇到某些 Bug, ⽐如 0.1 + 0.2 !== 0.3,可是這⼀塊的內容會在進階部分講 到。string 類型是不可變的,⽆論你在 string 類型上調⽤何種 ⽅法,都不會對值有改變。
另外對於 null 來講,不少⼈會認爲他是個對象類型,其實這是錯誤 的。雖然 typeof null 會輸出 object,可是這只是 JS 存在的⼀ 個悠久 Bug。在 JS 的最第一版本中使⽤的是 32 位系統,爲了性能考 慮使⽤低位存儲變量的類型信息,000 開頭表明是對象,然⽽ null 表示爲全零,因此將它錯誤的判斷爲 object 。雖然如今的內部類 型判斷代碼已經改變了,可是對於這個 Bug 倒是⼀直流傳下來。
在 JS 中,除了原始類型那麼其餘的都是對象類型了。對象類型和原 始類型不一樣的是,原始類型存儲的是值,對象類型存儲的是地址(指 針)。當你建立了⼀個對象類型的時候,計算機會在內存中幫咱們開 闢⼀個空間來存放值,可是咱們須要找到這個空間,這個空間會擁有 ⼀個地址(指針)。
const a = [];複製代碼
對於常量 a 來講,假設內存地址(指針)爲 #001,那麼在地址 #001 的位置存放了值 [],常量 a 存放了地址(指針) #001,再 看如下代碼
const a = [];
const b = a;
b.push(1);複製代碼
當咱們將變量賦值給另外⼀個變量時,複製的是本來變量的地址(指 針),也就是說當前變量 b 存放的地址(指針)也是 #001,當咱們 進⾏數據修改的時候,就會修改存放在地址(指針) #001 上的值, 也就致使了兩個變量的值都發⽣了改變。
接下來咱們來看函數參數是對象的狀況
function test(person) { person.age = 26 person = { name: 'yyy', age: 30 } return person }; const p1 = { name: 'yck', age: 25 }; const p2 = test(p1); console.log(p1) // -> ? console.log(p2) // -> ?複製代碼
對於以上代碼,你是否能正確的寫出結果呢?接下來讓我爲你解析⼀ 番:
因此最後 person 擁有了⼀個新的地址(指針),也就和 p1 沒有任何關係了,致使了最終兩個變量的值是不相同的。
typeof 對於原始類型來講,除了 null 均可以顯示正確的類型
typeof 1 // 'number' typeof '1' // 'string' typeof undefined // 'undefined' typeof true // 'boolean' typeof Symbol() // 'symbol' 複製代碼
typeof 對於對象來講,除了函數都會顯示 object,因此說 typeof 並不能準確判斷變量究竟是什麼類型
typeof [] // 'object' typeof {} // 'object' typeof console.log // 'function' 複製代碼
若是咱們想判斷⼀個對象的正確類型,這時候能夠考慮使⽤ instanceof,由於內部機制是經過原型鏈來判斷的,在後⾯的章節 中咱們也會⾃⼰去實現⼀個 instanceof。
const Person = function() {} const p1 = new Person() p1 instanceof Person // true var str = 'hello world' str instanceof String // false var str1 = new String('hello world') str1 instanceof String // true複製代碼
對於原始類型來講,你想直接經過 instanceof 來判斷類型是不⾏ 的,固然咱們仍是有辦法讓 instanceof 判斷原始類型的
class PrimitiveString { static [Symbol.hasInstance](x) { return typeof x === 'string' } } console.log('hello world' instanceof PrimitiveString) // true複製代碼
你可能不知道 Symbol.hasInstance 是什麼東⻄,其實就是⼀個 能讓咱們⾃定義 instanceof ⾏爲的東⻄,以上代碼等同於 typeof 'hello world' === 'string',因此結果⾃然是 true 了。這其實也側⾯反映了⼀個問題, instanceof 也不是百 分之百可信的。
function a() { return () => { return () => { console.log(this) } } } console.log(a()()())複製代碼
⾸先箭頭函數實際上是沒有 this 的,箭頭函數中的 this 只取決包裹 箭頭函數的第⼀個普通函數的 this。在這個例⼦中,由於包裹箭頭 函數的第⼀個普通函數是 a,因此此時的 this 是 window。另外對 箭頭函數使⽤ bind 這類函數是⽆效的。
最後種狀況也就是 bind 這些改變上下⽂的 API 了,對於這些函數 來講,this 取決於第⼀個參數,若是第⼀個參數爲空,那麼就是 window。
那麼說到 bind,不知道⼤家是否考慮過,若是對⼀個函數進⾏屢次 bind,那麼上下⽂會是什麼呢?
let a = {} let fn = function () { console.log(this) } fn.bind().bind(a)() // => ?複製代碼
若是你認爲輸出結果是 a,那麼你就錯了,其實咱們能夠把上述代碼 轉換成另⼀種形式
// fn.bind().bind(a) 等於 let fn2 = function fn1() { return function() { return fn.apply() }.apply(a) } fn2() 複製代碼
能夠從上述代碼中發現,無論咱們給函數 bind ⼏次,fn 中的 this 永遠由第⼀次 bind 決定,因此結果永遠是 window。
let a = { name: 'yck' } function foo() { console.log(this.name) } foo.bind(a)() // => 'yck'複製代碼
以上就是 this 的規則了,可是可能會發⽣多個規則同時出現的情 況,這時候不一樣的規則之間會根據優先級最⾼的來決定 this 最終指 向哪⾥。
⾸先,new 的⽅式優先級最⾼,接下來是 bind 這些函數,而後是 obj.foo() 這種調⽤⽅式,最後是 foo 這種調⽤⽅式,同時,箭 頭函數的 this ⼀旦被綁定,就不會再被任何⽅式所改變。
優勢
a、不須要插件支持
b、優秀的用戶體驗
c、提升Web程序的性能
d、減輕服務器和帶寬的負擔
缺點
a、瀏覽器對XMLHttpRequest對象的支持度不足,幾乎全部瀏覽器如今都支持
b、破壞瀏覽器「前進」、「後退」按鈕的正常功能,能夠經過簡單的插件彌補
c、對搜索引擎的支持不足
實現:
(1) JSONP跨域:利用script腳本容許引用不一樣域下的js實現的,將回調方法帶入服務器,返回結果時回調。
(2) 跨域資源共享(CORS)
跨域資源共享(CORS)是一種網絡瀏覽器的技術規範,它爲Web服務器定義了一種方式,容許網頁從不一樣的域訪問其資源。
CORS與JSONP相比:
a、 JSONP只能實現GET請求,而CORS支持全部類型的HTTP請求。
b、 使用CORS,開發者能夠使用普通的XMLHttpRequest發起請求和得到數據,比起JSONP有更好的錯誤處理。
c、 JSONP主要被老的瀏覽器支持,它們每每不支持CORS,而絕大多數現代瀏覽器都已經支持了CORS。
(1)、get 是從服務器上獲取數據,post 是向服務器傳送數據。 get 請求返回 request - URI 所指出的任意信息。
Post 請求用來發送電子郵件、新聞或發送能由交互用戶填寫的表格。這是惟一須要在請求中發送body的請求。使用Post請求時須要在報文首部 Content - Length 字段中指出body的長度。
(2)、get 是把參數數據隊列加到提交表單的ACTION屬性所指的URL中,值和表單內各個字段一一對應,在URL中能夠看到。post是經過HTTP post機制,將表單內各個字段與其內容放置在HTML HEADER內一塊兒傳送到ACTION屬性所指的URL地址,用戶看不到這個過程。
(3)、對於 get 方式,服務器端用Request.QueryString獲取變量的值,對於 post 方式,服務器端用Request.Form獲取提交的數據。
(4)、get 傳送的數據量較小,不能大於2KB。post 傳送的數據量較大,通常被默認爲不受限制。但理論上,IIS4中最大量爲80KB,IIS5中爲100KB。 用IIS過濾器的只接受get參數,因此通常大型搜索引擎都是用get方式。
(5)get安全性很是低,post 安全性相對較高。若是這些數據是中文數據並且是非敏感數據,那麼使用get;若是用戶輸入的數據不是中文字符並且包含敏感數據,那麼仍是使用 post 爲好。
Ajax的優點:
(1)、可搜索性
普通的文本網頁會更有利於SEO。文本內容是搜索引擎容易檢索的,而繁瑣的swf字節碼倒是搜索引擎不肯觸及的。雖然Google等一些大型的搜索引擎能夠檢索SWF內部的內容,可是仍然有不少麻煩存在。
(2)、開放性
Flash常年以來被Macromedia看的很死。包括Flex、FMS等輔佐技術一直都須要昂貴的安裝、維護費用。而JS則沒有這樣的麻煩。沒有人願意承擔法律和版權的風險。費用Flash開發是很昂貴的,由於FlashIDE等環境都是要收費的.而Ajax則不一樣.雖然有一些便宜的生成swf的工具,可是他們的工能實在沒法知足複雜需求。
(3)、易用性
Ajax程序有更好的易用性。因爲中間有一層Flashplayer代理層,所以許多輔助功能沒法被Flash靈活利用。並且Flash在一些方面有着很差的口碑。好比彈出廣告、好比惡意代碼。
(4)、易於開發
人們開發複雜的Ajax和Flash應用程序時,都會藉助一些高級的開發工具。廣泛來講,Ajax的開發包比Flash簡便、容易。
Flash的優點:
(1)、多媒體處理
Flash在音頻、視頻等多媒體領域相比HTML有絕對的優點。如今幾乎全部的網站都包含有Flash內容。
(2)、兼容性
兼容性好:因爲經過了惟一的FlashPlayer「代理」。人們沒必要像調試JS那樣,在不一樣的瀏覽器中調試程序。
(3)、矢量圖型
這是Flash最大的優點,一樣處在這一領域的SVG、Canvas element以及Direct徹底不能與Flash相比。
(4)、客戶端資源調度
Flash可以更容易的調用瀏覽器之外的外部資源。好比攝像頭、麥克風等。然而這是普通的HTML沒法完成的。可是這也許是一個缺點(爲何呢?)
Ajax的劣勢:
(1)、它可能破壞瀏覽器的後退功能
(2)、使用動態頁面更新使得用戶難於將某個特定的狀態保存到收藏夾中 ,不過這些都有相關方法解決。
Flash的劣勢:
(1)二進制格式
(2)格式私有
(3)flash 文件常常會很大,用戶第一次使用的時候須要忍耐較長的等待時間
(4)性能問題
舉個例子:普通B/S模式(同步)AJAX技術(異步)
同步:提交請求->等待服務器處理->處理完畢返回 這個期間客戶端瀏覽器不能幹任何事
異步: 請求經過事件觸發->服務器處理(這是瀏覽器仍然能夠做其餘事情)->處理完畢
ajax.open方法中,第3個參數是設同步或者異步。
prototype等js類庫通常都默認爲異步,即設爲true。先說下同步的狀況下,js會等待請求返回,獲取status。不須要onreadystatechange事件處理函數。而異步則須要 onreadystatechange事件處理,且值爲4再正確處理下面的內容。
//同步傳輸模式 function RequestByGet(nProducttemp,nCountrytemp) { var xmlhttp if (window.XMLHttpRequest) { //isIE = false; xmlhttp = new XMLHttpRequest(); }else if (window.ActiveXObject) { //isIE = true; xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } //Web page location. var URL="http://www.baidu.com/; xmlhttp.open("GET",URL, false); //xmlhttp.SetRequestHeader("Content-Type","text/html;charset="utf-8") xmlhttp.send(null); var result = xmlhttp.status; //OK if(result==200){ document.getElementById("div_RightBarBody").innerHTML=xmlhttp.responseText; } xmlhttp = null; }複製代碼
//異步傳輸模式 var xmlhttp function RequestByGet(nProducttemp,nCountrytemp) { if (window.XMLHttpRequest) { //isIE = false; xmlhttp = new XMLHttpRequest(); } else if (window.ActiveXObject) { //isIE = true; xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } //Web page location. var URL="http://www.baidu.com/"; xmlhttp.open("GET",URL, true); xmlhttp.onreadystatechange = handleResponse; //xmlhttp.SetRequestHeader("Content-Type","text/html;charset=UTF-8") xmlhttp.send(null); } function handleResponse() { if(xmlhttp.readyState == 4 && xmlhttp.status==200) { document.getElementById("div_RightBarBody").innerHTML=xmlhttp.responseText; xmlhttp = null; } } 複製代碼
回答一:
JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式。
它是基於JavaScript的一個子集。數據格式簡單, 易於讀寫, 佔用帶寬小.
json簡單說就是javascript中的對象和數組,因此這兩種結構就是對象和數組。
a、JSON對象:以「{」開始,以「}」結束,裏面則是一系列的鍵(key)值(value)對,鍵和值用「:」分開,每對鍵值對之間用「,」分開。參考如下語法結構:{key1:value1,key2:value2,key3:value3…}其中鍵(key)是字符串,而值(value)能夠是字符串,數值,true,false,null,對象或數組,也就是說某個鍵(key)的值(value)能夠是一個數組,數組裏面又是一些JSON對象,這種表示稍微複雜一些,可是參照這些理解能夠很容易分辨出來。
b、JSON數組:以」[」開始,」]」結束,如同程序語言同樣,例如C#,Button[] btnArray,則BtnArray是一個Button類型的數組,裏面就存放Button類型的對象,那麼JSON數組也同樣,裏面存放的也是JSON對象.
回答二:
a、JSON 指的是 JavaScript 對象表示法(JavaScript Object Notation)
b、JSON 是輕量級的文本數據交換格式,並非編程語言
c、JSON 獨立於語言存在
d、JSON 具備自我描述性,更易理解
e、JSON 能夠將 JavaScript 對象中表示的一組數據轉換爲字符串,而後就能夠在函數之間輕鬆地傳遞這個字符串,或者在異步應用程序中將字符串從 Web 客戶機傳遞給服務器端程序。這個字符串看起來有點兒古怪,可是JavaScript很容易解釋它,並且 JSON 能夠表示比"名稱 / 值對"更復雜的結構。例如,能夠表示數組和複雜的對象,而不只僅是鍵和值的簡單列表
回答一:
(1)、js的this指向是不肯定的,也就是說是能夠動態改變的。call/apply 就是用於改變this指向的函數,這樣設計可讓代碼更加靈活,複用性更高
(2)、this 通常狀況下,都是指向函數的擁有者。
(3)、在函數自執行裏,this 指向的是 window 對象。
擴展:關於this,還有一個地方比較讓人模糊的是在dom事件裏,一般有以下3種狀況:
a、使用標籤屬性註冊事件,此時this指向的是window對象。
b、對與a,要讓this指向input,能夠將this做爲參數傳遞。
c、使用addEventListener等註冊事件。此時this也是指向 input。
回答二:
(1)、處於全局做用域下的this:在全局做用域下this默認指向window對象。
this;/*window*/
var a = {name:this}/*window*/
var b =[this];/*window*/複製代碼
(2)、處在函數中的this,又分爲如下幾種狀況:
a、通常定義的函數,而後通常的執行:this仍是默認指向window。
var a = function(){ console.log(this); } a();/*window*/複製代碼
b、通常定義,用new調用執行:這時候讓this指向新建的空對象,咱們才能夠給空對象初始化自有變量
var a = function(){ console.log(this); } new a();/*新建的空對象*/複製代碼
c、做爲對象屬性的函數,調用時:這時候this指向調用f函數的a對象。
var a = { f:function(){ console.log(this) } } a.f();/*a對象*/複製代碼
(3)、經過call()和apply()來改變this的默認引用:
var b = {id: 'b'}; var a = { f:function(){ console.log(this) } } a.f.call(b); //{id: "b"}複製代碼
全部函數對象都有的call方法和apply方法,它們的用法大致類似,f.call(b)的意思是,執行f函數,並將f函數執行期活動對象裏的this指向b對象,這樣標示符解析時,this就會是b對象了。不過調用函數是要傳參的。因此,f.call(b, x, y); f.apply(b, [x, y]);以上就是用call方法執行f函數,與用apply方法執行f函數時傳參方式,它們之間的差別,你們一目瞭然:apply經過數組的方式傳遞參數,call經過一個個的形參傳遞參數。
(4)、一些函數特殊執行狀況this的指向問題:
a、setTimeout()和setInverval():
var a = function(){ console.log(this); } setTimeout(a,0);/*window*/複製代碼
setInterval()相似。
b、dom模型中觸發事件的回調方法執行中活動對象裏的this指向該dom對象。
(1)經過new 方法
var obj = new Object(); 複製代碼
(2) 工廠模式
function Parent(){ var Child = new Object(); Child.name="欲淚成雪"; Child.age="20"; return Child; }; var x = Parent()複製代碼
引用該對象的時候,這裏使用的是 var x = Parent()而不是 var x = new Parent();由於後者會可能出現不少問題(前者也成爲工廠經典方式,後者稱之爲混合工廠方式),不推薦使用new的方式使用該對象
(2)構造函數方式
function Parent(){ this.name="欲淚成雪"; this.age="20"; }; var x =new Parent();複製代碼
(3) 原型模式
function Parent(){}; Parent.prototype.name="欲淚成雪"; Parent.prototype.age="20"; var x =new Parent();複製代碼
(4)混合的構造函數,原型方式(推薦)
function Parent(){ this.name="欲淚成雪"; this.age=22; }; Parent.prototype.lev=function(){ return this.name; }; var x =new Parent();複製代碼
(5)動態原型方式
function Parent(){ this.name="欲淚成雪"; this.age=22; if(typeofParent._lev=="undefined"){ Parent.prototype.lev=function(){ return this.name; } Parent._lev=true; }} var x =new Parent();複製代碼
回答一:
(1)、IE7/8 DOM對象或者ActiveX對象循環引用致使內存泄漏
a、多個對象循環引用
b、循環引用本身
(2)、基礎的DOM泄漏
當原有的DOM被移除時,子結點引用沒有被移除則沒法回收。
(3)、timer定時器泄漏
這個時候你沒法回收buggyObject,解決辦法,先中止timer而後再回收
回答二:
內存泄漏指任何對象在您再也不擁有或須要它以後仍然存在。
垃圾回收器按期掃描對象,並計算引用了每一個對象的其餘對象的數量。若是一個對象的引用數量爲 0(沒有其餘對象引用過該對象),或對該對象的唯一引用是循環的,那麼該對象的內存便可回收。
setTimeout 的第一個參數使用字符串而非函數的話,會引起內存泄漏。
閉包、控制檯日誌、循環(在兩個對象彼此引用且彼此保留時,就會產生一個循環)也會引起內存泄漏問題。
a、在一個對象上觸發某類事件(好比單擊onclick事件),若是此對象定義了此事件的處理程序,那麼此事件就會調用這個處理程序,若是沒有定義此事件處理程序或者事件返回true,那麼這個事件會向這個對象的父級對象傳播,從裏到外,直至它被處理(父級對象全部同類事件都將被激活),或者它到達了對象層次的最頂層,即document對象(有些瀏覽器是window)。
b、冒泡型事件:事件按照從最特定的事件目標到最不特定的事件目標(document對象)的順序觸發
c、js冒泡機制是指若是某元素定義了事件A,如click事件,若是觸發了事件以後,沒有阻止冒泡事件,那麼事件將向父級元素傳播,觸發父類的click函數。
//阻止冒泡時間方法,兼容ie(e.cancleBubble)和ff(e.stopProgation)
function stopBubble(e){ var evt = e||window.event; evt.stopPropagation?evt.stopPropagation():(evt.cancelBubble=true);//阻止冒泡 evt.preventDefault }複製代碼
ES6 原生提供了 Promise 對象。
所謂 Promise,就是一個對象,用來傳遞異步操做的消息。它表明了某個將來纔會知道結果的事件(一般是一個異步操做),而且這個事件提供統一的 API,可供進一步處理。
Promise 對象有如下兩個特色。
(1)、對象的狀態不受外界影響。Promise 對象表明一個異步操做,有三種狀態:Pending(進行中)、Resolved(已完成,又稱 Fulfilled)和 Rejected(已失敗)。只有異步操做的結果,能夠決定當前是哪種狀態,任何其餘操做都沒法改變這個狀態。這也是 Promise 這個名字的由來,它的英語意思就是「承諾」,表示其餘手段沒法改變。
(2)、一旦狀態改變,就不會再變,任什麼時候候均可以獲得這個結果。Promise 對象的狀態改變,只有兩種可能:從 Pending 變爲 Resolved 和從 Pending 變爲 Rejected。只要這兩種狀況發生,狀態就凝固了,不會再變了,會一直保持這個結果。就算改變已經發生了,你再對 Promise 對象添加回調函數,也會當即獲得這個結果。這與事件(Event)徹底不一樣,事件的特色是,若是你錯過了它,再去監聽,是得不到結果的。
有了 Promise 對象,就能夠將異步操做以同步操做的流程表達出來,避免了層層嵌套的回調函數。此外,Promise 對象提供統一的接口,使得控制異步操做更加容易。
Promise 也有一些缺點。首先,沒法取消 Promise,一旦新建它就會當即執行,沒法中途取消。其次,若是不設置回調函數,Promise 內部拋出的錯誤,不會反應到外部。第三,當處於 Pending 狀態時,沒法得知目前進展到哪個階段(剛剛開始仍是即將完成)。
(1)、標記清除(mark and sweep)
這是`JavaScript`最多見的垃圾回收方式,當變量進入執行環境的時候,好比函數中聲明一個變量,垃圾回收器將其標記爲「進入環境」,當變量離開環境的時候(函數執行結束)將其標記爲「離開環境」。
垃圾回收器會在運行的時候給存儲在內存中的全部變量加上標記,而後去掉環境中的變量以及被環境中變量所引用的變量(閉包),在這些完成以後仍存在標記的就是要刪除的變量了
(2)、引用計數(reference counting)
在低版本`IE`中常常會出現內存泄露,不少時候就是由於其採用引用計數方式進行垃圾回收。引用計數的策略是跟蹤記錄每一個值被使用的次數,當聲明瞭一個 變量並將一個引用類型賦值給該變量的時候這個值的引用次數就加1,若是該變量的值變成了另一個,則這個值得引用次數減1,當這個值的引用次數變爲0的時 候,說明沒有變量在使用,這個值無法被訪問了,所以能夠將其佔用的空間回收,這樣垃圾回收器會在運行的時候清理掉引用次數爲0的值佔用的空間。
在IE中雖然`JavaScript`對象經過標記清除的方式進行垃圾回收,但BOM與DOM對象倒是經過引用計數回收垃圾的,也就是說只要涉及BOM及DOM就會出現循環引用問題。
JavaScript是一種經過原型實現繼承的語言與別的高級語言是有區別的,像java,C#是經過類型決定繼承關係的,JavaScript是的動態的弱類型語言,總之能夠認爲JavaScript中全部都是對象,在JavaScript中,原型也是一個對象,經過原型能夠實現對象的屬性繼承,JavaScript的對象中都包含了一個" prototype"內部屬性,這個屬性所對應的就是該對象的原型。
"prototype"做爲對象的內部屬性,是不能被直接訪問的。因此爲了方便查看一個對象的原型,Firefox和Chrome內核的JavaScript引擎中提供了"__proto__"這個非標準的訪問器(ECMA新標準中引入了標準對象原型訪問器"Object.getPrototype(object)")。
原型的主要做用就是爲了實現繼承與擴展對象。
在 JavaScript 中,判斷一個變量的類型能夠用typeof
(1)、數字類型, typeof 返回的值是 number。好比說:typeof(1),返回值是number
(2)、字符串類型, typeof 返回的值是 string。好比typeof("123")返回值是string。
(3)、布爾類型, typeof 返回的值是 boolean 。好比typeof(true)返回值是boolean。
(4)、對象、數組、null 返回的值是 object 。好比typeof(window),typeof(document),typeof(null)返回的值都是object。
(5)、函數類型,返回的值是 function。好比:typeof(eval),typeof(Date)返回的值都是function。
(6)、不存在的變量、函數或者undefined,將返回undefined。好比:typeof(abc)、typeof(undefined)都返回undefined。
在JavaScript 中,instanceof用於判斷某個對象是否被另外一個函數構造。
使用 typeof 運算符時採用引用類型存儲值會出現一個問題,不管引用的是什麼類型的對象,它都返回 "object"。ECMAScript 引入了另外一個 Java 運算符 instanceof 來解決這個問題。instanceof 運算符與 typeof 運算符類似,用於識別正在處理的對象的類型。與 typeof 方法不一樣的是,instanceof 方法要求開發者明確地確認對象爲某特定類型。
爲了說明 JavaScript 是一門完全的面向對象的語言,首先有必要從面向對象的概念着手 , 探討一下面向對象中的幾個概念:
a、一切事物皆對象
b、對象具備封裝和繼承特性
c、對象與對象之間使用消息通訊,各自存在信息隱藏
以這三點作爲依據,C++ 是半面向對象半面向過程語言,由於,雖然他實現了類的封裝、繼承和多態,但存在非對象性質的全局函數和變量。Java、C# 是徹底的面嚮對象語言,它們經過類的形式組織函數和變量,使之不能脫離對象存在。但這裏函數自己是一個過程,只是依附在某個類上。
然而,面向對象僅僅是一個概念或者編程思想而已,它不該該依賴於某個語言存在。好比 Java 採用面向對象思想構造其語言,它實現了類、繼承、派生、多態、接口等機制。可是這些機制,只是實現面向對象編程的一種手段,而非必須。換言之,一門語言能夠根據其自身特性選擇合適的方式來實現面向對象。因此,因爲大多數程序員首先學習或者使用的是相似 Java、C++ 等高級編譯型語言(Java 雖然是半編譯半解釋,但通常作爲編譯型來說解),於是先入爲主地接受了「類」這個面向對象實現方式,從而在學習腳本語言的時候,習慣性地用類式面嚮對象語言中的概念來判斷該語言是不是面嚮對象語言,或者是否具有面向對象特性。這也是阻礙程序員深刻學習並掌握 JavaScript 的重要緣由之一。
JavaScript 語言是經過一種叫作 原型(prototype)的方式來實現面向對象編程的。下面就來討論 基於類的(class-based)面向對象和 基於原型的 (prototype-based) 面向對象這兩種方式在構造客觀世界的方式上的差異。
基於類的面向對象和基於原型的面向對象方式比較,在基於類的面向對象方式中,對象(object)依靠類(class)來產生。而在基於原型的面向對象方式中,對象(object)則是依靠構造器(constructor)利用原型(prototype)構造出來的。舉個客觀世界的例子來講明二種方式認知的差別。例如工廠造一輛車,一方面,工人必須參照一張工程圖紙,設計規定這輛車應該如何製造。這裏的工程圖紙就比如是語言中的 類 (class),而車就是按照這個 類(class)製造出來的;另外一方面,工人和機器 ( 至關於 constructor) 利用各類零部件如發動機,輪胎,方向盤 ( 至關於 prototype 的各個屬性 ) 將汽車構造出來。
事實上關於這兩種方式誰更爲完全地表達了面向對象的思想,目前尚有爭論。但認爲原型式面向對象是一種更爲完全的面向對象方式,理由以下:
(1)、首先,客觀世界中的對象的產生都是其它實物對象構造的結果,而抽象的「圖紙」是不能產生「汽車」的,也就是說,類是一個抽象概念而並不是實體,而對象的產生是一個實體的產生;
(2)、其次,按照一切事物皆對象這個最基本的面向對象的法則來看,類 (class) 自己並非一個對象,然而原型方式中的構造器 (constructor) 和原型 (prototype) 自己也是其餘對象經過原型方式構造出來的對象。
(3)、再次,在類式面嚮對象語言中,對象的狀態 (state) 由對象實例 (instance) 所持有,對象的行爲方法 (method) 則由聲明該對象的類所持有,而且只有對象的結構和方法可以被繼承;而在原型式面嚮對象語言中,對象的行爲、狀態都屬於對象自己,而且可以一塊兒被繼承(參考資源),這也更貼近客觀實際。
(4)、最後,類式面嚮對象語言好比 Java,爲了彌補沒法使用面向過程語言中全局函數和變量的不便,容許在類中聲明靜態 (static) 屬性和靜態方法。而實際上,客觀世界不存在所謂靜態概念,由於一切事物皆對象!而在原型式面嚮對象語言中,除內建對象 (build-in object) 外,不容許全局對象、方法或者屬性的存在,也沒有靜態概念。
全部語言元素 (primitive) 必須依賴對象存在。但因爲函數式語言的特色,語言元素所依賴的對象是隨着運行時 (runtime) 上下文 context變化而變化的,具體體如今this指針的變化。正是這種特色更貼近「萬物皆有所屬,宇宙乃萬物生存之根本」的天然
javascript中的函數就是對象,對象就是「鍵/值」對的集合並擁有一個鏈接到原型對隱藏鏈接。
(1)、參數對象 (arguments)
第一個函數中有一個默認對象叫arguments,相似數組,但不是數組,該對象是傳遞給函數的參數。
(2)、構造函數
在javascript中對象構造函數能夠建立一個對象。
(3)、函數調用
a、call:調用一個對象的一個方法,以另外一個對象替換當前對象
b、apply:應用某一對象的一個方法,用另外一個對象替換當前對象,與call相似。
c、caller:在一個函數調用另外一個函數時,被調用函數會自動生成一個caller屬性,指向調用它的函數對象。若是該函數當前未被調用,或並不是被其餘函數調用,則caller爲null。
d、Callee:當函數被調用時,它的arguments.callee對象就會指向自身,也就是一個
對本身的引用。
IIFE即Immediately-Invoked Function Expression,當即執行函數表達式, 當即執行的函數表達式的執行括號應該寫在外包括號內。雖然寫在內仍是寫在外都是有效的,但寫在內使得整個表達式看起來更像一個總體,所以推薦這麼作。
//最經常使用的兩種寫法 (function(){ /* code */ }()); // 老師推薦寫法 (function(){ /* code */ })(); // 固然這種也能夠 // 括號和JS的一些操做符(如 =&& || ,等)能夠在函數表達式和函數聲明上消除歧義 // 以下代碼中,解析器已經知道一個是表達式了,因而也會把另外一個默認爲表達式 // 可是二者交換則會報錯 var i = function(){ return 10; }(); true && function(){ /* code */ }();0, function(){ /* code */ }(); // 若是你不怕代碼晦澀難讀,也能夠選擇一元運算符!function(){ /* code */ }(); ~function(){ /* code */ }(); -function(){ /* code */ }(); +function(){ /* code */ }(); // 你也能夠這樣 new function(){ /* code */ } new function(){ /* code */ }() // 帶參複製代碼
IIFE的做用
(1)、提升性能:減小做用域查找時間。使用IIFE的一個微小的性能優點是經過匿名函數的參數傳遞經常使用全局對象window、document、jQuery,在做用域內引用這些全局對象。JavaScript解釋器首先在做用域內查找屬性,而後一直沿着鏈向上查找,直到全局範圍。將全局對象放在IIFE做用域內提高js解釋器的查找速度和性能。
(2)、壓縮空間:經過參數傳遞全局對象,壓縮時能夠將這些全局對象匿名爲一個更加精簡的變量名
(3)、避免衝突:匿名函數內部能夠造成一個塊級的私有做用域。
(4)、依賴加載:能夠靈活的加載第三方插件,固然使用模塊化加載更好(AMD,CMD)
Function
函數就是對象,表明函數的對象就是函數對象。全部的函數對象是被Function這個函數對象構造出來的。Function是最頂層的構造器。它構造了系統中全部的對象,包括用戶自定義對象,系統內置對象,甚至包括它自已。這也代表Function具備自舉性(自已構造本身的能力)。這也間接決定了Function的call和constructor邏輯相同。每一個對象都有一個 constructor 屬性,用於指向建立其的函數對象。
a、函數與對象具備相同的語言地位
b、沒有類,只有對象
c、函數也是一種對象,所謂的函數對象
d、對象是按引用來傳遞的
Object
對於Object它是最頂層的對象,全部的對象都將繼承Object的原型,可是你也要明確的知道Object也是一個函數對象,因此說Object是被Function構造出來的。
(1)、本地對象
ECMA-262 把本地對象(native object)定義爲「獨立於宿主環境的 ECMAScript 實現提供的對象」。
再來看一下,「本地對象」包含哪些內容:
Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError
由此能夠看出,簡單來講,本地對象就是 ECMA-262 定義的類(引用類型)。
(2)、內置對象
ECMA-262 把內置對象(built-in object)定義爲「由 ECMAScript 實現提供的、獨立於宿主環境的全部對象,在 ECMAScript 程序開始執行時出現」。這意味着開發者沒必要明確實例化內置對象,它已被實例化了。
一樣是「獨立於宿主環境」。根據定義咱們彷佛很難分清「內置對象」與「本地對象」的區別。而ECMA-262 只定義了兩個內置對象,即 Global 和 Math (它們也是本地對象,根據定義,每一個內置對象都是本地對象)。
如此就能夠理解了。內置對象是本地對象的一種。而其包含的兩種對象中,Math對象咱們常常用到,可這個Global對象是啥東西呢?
Global對象是ECMAScript中最特別的對象,由於實際上它根本不存在,但你們要清楚,在ECMAScript中,不存在獨立的函數,全部函數都必須是某個對象的方法。相似於isNaN()、parseInt()和parseFloat()方法等,看起來都是函數,而實際上,它們都是Global對象的方法。
(3)、宿主對象
由ECMAScript實現的宿主環境提供的對象,即咱們網頁的運行環境(操做系統和瀏覽器),全部的BOM和DOM都是宿主對象。
宿主環境提供的全局方法:
alert、confirm、prompt、write、writeln(後面的兩種是document的方法)
內置對象是本地對象的一種,本地對象時由官方定義的,而宿主對象至關於由本身定義的對象、DOM對象和BOM對象組成的
a、變量定義
能夠使用var定義變量,變量若是沒有賦值,那變量的初始值爲undefined。
b、變量做用域
變量做用域指變量起做用的範圍。變量分爲全局變量和局部變量。全局變量在全局都擁有定義;而局部變量只能在函數內有效。
在函數體內,同名的局部變量或者參數的優先級會高於全局變量。也就是說,若是函數內存在和全局變量同名的局部變量或者參數,那麼全局變量將會被局部變量覆蓋。 全部不使用var定義的變量都視爲全局變量。
命名空間
封閉空間
js模塊化mvc(數據層、表現層、控制層)
seajs
變量轉換成對象的屬性
對象化
function Person(name){ this.name = name; } Person.prototype.showName = function(){ alert(this.name); } function Worker(name, job){ Person.apply(this,arguments) this.job = job; } for(var i in Person.prototype){ Worker.prototype = Person.prototype; } new Worker('sl', 'coders').showName();複製代碼
事件: 如onclick this->發生事件的對象
構造函數 this->new 出來的object
call/apply 改變this
代碼重用
避免全局變量(命名空間,封閉空間,模塊化mvc..)
拆分函數避免函數過於臃腫
註釋
1).建立ajax對象(XMLHttpRequest/ActiveXObject(Microsoft.XMLHttp))
2)判斷數據傳輸方式(GET/POST)
3)打開連接 open()
4)發送 send()
5) 當ajax對象完成第四步(onreadystatechange)數據接收完成,判斷http響應狀態(status)200-300之間或者304(緩存)執行回調函數
具體來講,事件委託就是事件目標自身不處理事件,而是把處理任務委託給其父元素或者祖先元素,甚至根元素(document)。jQuery爲綁定和委託事件提供了.bind()、.live()和.delegate()方法
1..bind()只能給調用它的時候已經存在的元素綁定事件,不能給將來新增的元素綁定事件在下列狀況下,應該使用.live()或.delegate(),而不能使用.bind():
2.爲DOM中的不少元素綁定相同事件;
3.爲DOM中尚不存在的元素綁定事件;
apply:方法能劫持另一個對象的方法,繼承另一個對象的屬性.
Function.apply(obj,args)方法能接收兩個參數
obj:這個對象將代替Function類裏this對象
args:這個是數組,它將做爲參數傳給Function(args-->arguments)
call:和apply的意思同樣,只不過是參數列表不同.
Function.call(obj,[param1[,param2[,…[,paramN]]]])
obj:這個對象將代替Function類裏this對象
params:這個是一個參數列表
在給對象參數的狀況下,若是參數的形式是數組的時候,好比apply示例裏面傳遞了參數arguments,這個參數是數組類型,而且在調用Person的時候參數的列表是對應一致的(也就是Person和Student的參數列表前兩位是一致的) 就能夠採用 apply , 若是個人Person的參數列表是這樣的(age,name),而Student的參數列表是(name,age,grade),這樣就能夠用call來實現了,也就是直接指定參數列表對應值的位置(Person.call(this,age,name,grade));
apply的一些其餘巧妙用法
調用apply方法的時候,第一個參數是對象(this), 第二個參數是一個數組集合,在調用Person的時候,他須要的不是一個數組,可是爲何他給我一個數組我仍然能夠將數組解析爲一個一個的參數,
這個就是apply的一個巧妙的用處,能夠將一個數組默認的轉換爲一個參數列表([param1,param2,param3] 轉換爲 param1,param2,param3) 這個若是讓咱們用程序來實現將數組的每個項,來裝換爲參數的列表,可能都得費一會功夫,藉助apply的這點特性,因此就有了如下高效率的方法:
function fun(n,o) { console.log(o) return { fun:function(m){ return fun(m,n); } }; } var a = fun(0); a.fun(1); a.fun(2); a.fun(3); var b = fun(0).fun(1).fun(2).fun(3); var c = fun(0).fun(1); c.fun(2); c.fun(3); //undefined, 0, 0, 0 //undefined, 0, 1, 2 //undefined, 0, 1, 1複製代碼
<ul id="test"> <li>這是第一條alert(0);</li> <li>這是第二條alert(1);</li> <li>這是第三條alert(2);</li> </ul> <script type="text/javascript"> var elements = document.getElementById('test').querySelectorAll('li'); for (var i = 0; i < elements.length; i++) { elements[i].onclick = function () { alert(i); } } </script>//點擊每一條都alert:2複製代碼
function A(){ } function B(a){ this.a = a; } function C(a){ if(a){ this.a = a; } } A.prototype.a = 1; B.prototype.a = 1; C.prototype.a = 1; console.log(new A().a); console.log(new B().a); console.log(new C(2).a); 結果: 一、undefined、 2. 複製代碼
var F = function(){}; Object.prototype.a = function(){}; Function.prototype.b = function(){}; var f = new F();複製代碼
問:調用f.a( )和f.b( ) 能成功麼?
答案:能調用f.a( )可是不能調用f.b( );
使用面向對象的混合模式實現小狗的建立 function Dog() { this.name = '小狗狗'; this.wow = 'wow'; } Dog.prototype.yelp = function() { console.log(this.wow); } function MadDog() { Dog.call(this); this.name = '精力旺盛的狗狗'; } for (var i in Dog.prototype) { MadDog.prototype[i] = Dog.prototype[i]; }; MadDog.prototype.yelp = function () { var _this = this; setInterval(function(){ console.log(_this.wow); }, 5000); } var dog = new MadDog(); dog.yelp();複製代碼
100 Continue繼續,通常在發送post請求時,已發送了http header以後服務端將返回此信息,表示確認,以後發送具體參數信息
200 OK 正常返回信息
201 Created請求成功而且服務器建立了新的資源
202 Accepted服務器已接受請求,但還沒有處理
301 Moved Permanently請求的網頁已永久移動到新位置。
302 Found 臨時性重定向。
303 See Other臨時性重定向,且老是使用 GET 請求新的 URI。
304 Not Modified自從上次請求後,請求的網頁未修改過。
400 Bad Request服務器沒法理解請求的格式,客戶端不該當嘗試再次使用相同的內容發起請求。
401 Unauthorized 請求未受權。
403 Forbidden 禁止訪問。
404 Not Found 找不到如何與URI 相匹配的資源。
500 Internal ServerError 最多見的服務器端錯誤。
503 Service Unavailable服務器端暫時沒法處理請求(多是過載或維護)。
(1) 減小http請求次數:CSSSprites, JS、CSS源碼壓縮、圖片大小控制合適;網頁Gzip,CDN 託管,data 緩存 ,圖片服務器。
(2) 讓ajax可緩存, 前端模板JS+數據,減小因爲HTML標籤致使的帶寬浪費,前端用變量保存 ajax 請求結果,每次操做本地變量,不用請求,減小請求次數
(3)用 innerHTML 代替 DOM 操做,減小 DOM 操做次數,優化 javascript 性能。
(4)當須要設置的樣式不少時設置 className 而不是直接操做style。
(5)少用全局變量、緩存 DOM 節點查找的結果。減小 IO 讀取操做。
(6) 避免使用 CSSExpression(css表達式)又稱Dynamic properties(動態屬性)。
(7)圖片預加載,將樣式表放在頂部(CSS使用<link>標籤放在頂部),將腳本放在底部 加上時間戳。
(8)合理使用 HTTP 緩存
(9) JS去除重複腳本
(10) 優化圖片、儘可能使用PNG
(11) 延遲加載組件
(12) 減小DOM元素的數量
內存泄漏指任何對象在您再也不擁有或須要它以後仍然存在。
垃圾回收器按期掃描對象,並計算引用了每一個對象的其餘對象的數量。若是一個對象的引用數量爲0(沒有其餘對象引用過該對象),或對該對象的唯一引用是循環的,那麼該對象的內存便可回收。
setTimeout的第一個參數使用字符串而非函數的話,會引起內存泄漏。
閉包、控制檯日誌、循環(在兩個對象彼此引用且彼此保留時,就會產生一個循環)。
(function() { var a = b = 5; })(); console.log(b); 答案:5複製代碼
function test() { console.log(a); console.log(foo()); var a = 1; function foo() { return 2; } } test();複製代碼
這段代碼的結果是 undefined 和 2。
var fullname = 'John Doe'; var obj = { fullname: 'Colin Ihrig', prop: { fullname: 'Aurelio De Rosa', getFullname: function() { return this.fullname; } } }; console.log(obj.prop.getFullname()); var test = obj.prop.getFullname; console.log(test()); 答案是Aurelio De Rosa和John Doe。複製代碼
e. stopPropagation();//標準瀏覽器阻止事件冒泡 event.canceBubble=true;//ie9以前阻止默認事件:爲了避免讓a點擊以後跳轉,咱們就要給他的點擊事件進行阻止return falsee.preventDefault();複製代碼
一、建立一個空對象,而且 this 變量引用該對象,同時還繼承了該函數的原型。
二、屬性和方法被加入到 this 引用的對象中。
三、新建立的對象由 this 所引用,而且最後隱式的返回 this 。
(1) 版本設置
(2) 主要是避免緩存,每次修改css文件後,從新引用更改後面的參數,這樣就會從新請求文件,不會使用緩存。
(3) 實現控制某個外部js或者css文件的加載順序
async 表示讓當即加載腳本
defer表示腳本能夠延遲加載,等整個頁面加載完之後再加載js或者css。目的就是控制夾雜順序
(1) IE下載的順序是從上到下,渲染的順序也是從上到下,下載和渲染是同時進行的
(2)在渲染到頁面的某一部分時,其上面的全部部分都已經下載完成(並非說全部相關聯的元素都已經下載完);
(3)在下載過程當中,若是遇到某一標籤是嵌入文件,而且文件是具備語義解釋性的(例如:JS腳本,CSS樣式),那麼此時IE的下載過程會啓用單獨鏈接進行下載,而且在下載後進行解析,解析( JS、CSS中若有重定義,後定義函數將覆蓋前定義函數)過程當中,中止頁面全部往下元素的下載;
(4)樣式表文件比較特殊,在其下載完成後,將和之前下載的全部樣式表一塊兒進行解析,解析完成後,將對此前全部元素(含之前已經渲染的)從新進行樣式渲染。並以此方式一直渲染下去,直到整個頁面渲染完成。
答案:涉及到人手、分工、同步
(1) 先期團隊必須肯定好全局樣式,編碼模式等
(2) 編寫習慣必須一致
(3) 標註樣式編寫人,各模塊都及時標註(標註關鍵樣式調用的地方)
(4) 頁面進行標註
(5) Css與html分文件夾並行存放,命名都要統一
(6) Js分文件夾存放,命名以該JS功能爲準英文翻譯
(7) 圖片採用整合的.png格式文件使用,儘可能整合在一塊兒,方便未來的管理
防抖:觸發高頻事件後n秒內函數只會執行一次,若是n秒內高頻事件再次被觸發,則從新計算時間
思路:每次觸發事件時都取消以前的延時調用方法
function debounce (fn) { let timeout = null; // 建立一個標記用來存放定時器的返回值 return function () { clearTimeout(timeout); // 每當用戶輸入的時候把前一個 setTimeout clear 掉 timeout = setTimeout(() => { // 而後又建立一個新的 setTimeout, 這樣就能保證輸入字符後的 interval 間隔內 // 若是還有字符輸入的話,就不會執行 fn 函數 fn.apply(this, arguments); }, 500); }; } function sayHi() { console.log('防抖成功'); } var inp = document.getElementById('inp'); inp.addEventListener('input', debounce(sayHi)); // 防抖複製代碼
節流:高頻事件觸發,但在n秒內只會執行一次,因此節流會稀釋函數的執行頻率
思路:每次觸發事件時都判斷當前是否有等待執行的延時函數
function throttle(fn) { let canRun = true; // 經過閉包保存一個標記 return function () { if (!canRun) return; // 在函數開頭判斷標記是否爲true,不爲true則return canRun = false; // 當即設置爲false setTimeout(() => { // 將外部傳入的函數的執行放在setTimeout中 fn.apply(this, arguments); // 最後在setTimeout執行完畢後再把標記設置爲true(關鍵)表示能夠執行下一次循環了。 //當定時器沒有執行的時候標記永遠是false,在開頭被return掉 canRun = true; }, 500); }; } function sayHi(e) { console.log(e.target.innerWidth, e.target.innerHeight); } window.addEventListener('resize', throttle(sayHi));複製代碼
Http 的緩存主要利用 header 裏的兩個字段來控制:
Cache-control主要包含以及幾個字段:
private:則只有客戶端能夠緩存
public:客戶端和代理服務器均可以緩存
max-age:緩存的過時時間
no-cache:須要使用對比緩存來驗證緩存數據
no-store:全部內存都不會進行緩存
ETag:即用來進行對比緩存,Etag 是服務端資源的一個標識碼
當客戶端發送第一次請求時服務端會下發當前請求資源的標識碼 Etag,下次再請求時,客戶端則會經過 header 裏的 If-None-Match 將這個標識碼 Etag 帶上,服務端將客戶端傳來的 Etag 與最新的資源 Etag 作對比,若是同樣,則表示資源沒有更新,返回 304。
經過 Cache-control 和 Etag 的配合來實現 Http 的緩存機制。
deferred對象是從jQuery 1.5.0版本開始引入的一個新功能。
a、什麼是deferred對象
開發網站的過程當中,咱們常常遇到某些耗時很長的javascript操做。其中,既有異步的操做(好比ajax讀取服務器數據),也有同步的操做(好比遍歷一個大型數組),它們都不是當即能獲得結果的。
一般的作法是,爲它們指定回調函數(callback)。即事先規定,一旦它們運行結束,應該調用哪些函數。
可是,在回調函數方面,jQuery的功能很是弱。爲了改變這一點,jQuery開發團隊就設計了deferred對象。
簡單說,deferred對象就是jQuery的回調函數解決方案。在英語中,defer的意思是"延遲",因此deferred對象的含義就是"延遲"到將來某個點再執行。
它解決了如何處理耗時操做的問題,對那些操做提供了更好的控制,以及統一的編程接口。
b、它的主要功能,能夠歸結爲四點:
(1)、實現鏈式操做
(2)、指定同一操做的多個回調函數
(3)、爲多個操做指定回調函數
(4)、普通操做的回調函數接口
$.extend
在jQuery根命名空間下直接調用的方法能夠認爲是jQuery的靜態方法或屬性,經常使用方法名來調用,使用.方法名來調用,使用.extend這個靜態方法能夠完成兩個功能:
a、擴展屬性或方法給jQuery
b、擴展對象
$.fn.extend
.fn就是jQuery的原型,.fn等於jQuery.prototype,是jQuery的別名。.fn.extend方法的做用是用於擴展jQuery實例對象,也就是咱們從頁面中得到的jQuery對象。
.fn擴展了jQuery的原型,讓全部的jQuery實例對象都獲得的擴展的方法,其它也能夠直接修改jQuery.prototype來實現,.fn是jQuery.prototype的簡寫
幾乎在全部基於「類型」的語言中若是調用一個方法後將對象做爲方法參數返回則就會造成鏈式編程鏈式編程是將多個操做(多行代碼)經過點號"."連接在一塊兒成爲一句代碼。 鏈式代碼一般要求操做有返回值, 但對於不少操做大都是void型,什麼也不返回,這樣就很難鏈起來了, 固然也有解決辦法,可能不太優雅。 鏈式編程的新思想在jQuery中已流行使用
示例:
return $.each(this,function(index, obj) { $("<span/>").html("+").css("cursor","pointer").click(function() { $(obj).width($(obj).width()+ length); }).insertAfter(obj); });複製代碼
上面的示例中當$.each循環完成後返回this對象,返回的仍然是一個jQuery對象,因此能夠繼續jQuery編程。
$("button").SuperPlus(10).height(26).width(100).css("color","blue");複製代碼
window.load 是整個文檔結構和資源都加載完成執行此事件
documen ready 是整個文檔結構加載完成便可執行
回答:其實美圓符號$只是」jQuery」的別名,它是jQuery的選擇器,以下代碼:
// aaa(a); $(document).ready(function(){ /.../ });複製代碼
固然你也能夠用jQuery來代替$,以下代碼:
jQuery(document).ready(function(){ /.../ });複製代碼
jQuery中就是經過這個美圓符號來實現各類靈活的DOM元素選擇的,例如$(「#main」)即選中id爲main的元素。
從我本身的角度來說,能夠有3種類型的選擇器,以下:
一、基本選擇器:直接根據id、css類名、元素名返回匹配的dom元素。
二、層次選擇器:也叫作路徑選擇器,能夠根據路徑層次來選擇相應的DOM元素。
三、過濾選擇器:在前面的基礎上過濾相關條件,獲得匹配的dom元素。
四、請使用jQuery將頁面上的全部元素邊框設置爲2px寬的虛線?
代碼以下:
<script language="javascript" type="text/javascript"> $("*").css("border", "2px dotted red"); </script>複製代碼