Javascript是一門面向對象的,跨平臺的腳本語言。css
做用域:變量的做用範圍,主要有如下幾種:html
做用範圍爲整個程序的執行範圍,在函數體外部定義的變量就是全局變量,在函數體內部不使用var定義的也是全局變量。前端
做用範圍是某個函數體內部,在函數體內部經過var關鍵字定義的變量或者形參,都是局部變量,當局部變量與全局變量重名時,在函數體內部局部變量優先於全局變量。vue
變量的聲明會提高至當前做用域的最頂端,但不會提高賦值web
在相同的函數或塊做用域內從新聲明同一個變量會引起SyntaxError;面試
在聲明變量或常量以前使用它, 會引起ReferenceError. 這就是暫存性死區。正則表達式
這裏主要存在兩個坑點:編程
switch (x) {
case 0: let foo; break; case 1: let foo; // TypeError for redeclaration. break; } 複製代碼
會報錯是由於switch中只存在一個塊級做用域, 改爲如下形式能夠避免:api
let x = 1;
switch(x) { case 0: { let foo; break; } case 1: { let foo; break; } } 複製代碼
function test(){ var foo = 33; if (true) { let foo = (foo + 55); // ReferenceError } } test(); 複製代碼
在if語句中使用了let聲明瞭foo, 所以在(foo+55)中引用的是if塊級做用域中的foo, 而不是test函數中的foo; 可是因爲if中的foo尚未聲明完。數組
在這一行中,if塊的「foo」已經在詞法環境中建立,但還沒有達到(並終止)其初始化(這是語句自己的一部分)
所以它仍處於暫存死區
全局變量的生命週期直至瀏覽器卸載頁面纔會結束。 局部變量只在函數的執行過程當中存在,而在這個過程當中會爲局部變量在棧或堆上分配相應的空間,以存儲它們的值,而後再函數中使用這些變量,直至函數結束
執行環境執行棧(也稱執行上下文–execution context)。
當JavaScript解釋器初始化執行代碼時,它首先默認進入全局執行環境,今後刻開始,函數的每次調用都會建立一個新的執行環境,每個執行環境都會建立一個新的環境對象壓入棧中。
當執行流進入一個函數時,函數的環境對象就會被壓入一個環境棧中(execution stack)。在函數執行完後,棧將其環境彈出,把控制權返回給以前的執行環境。
除了正常運行模式,ECMAscript 5 添加了第二種運行模式:"嚴格模式"(strict mode)。顧名思義,這種模式使得Javascript在更嚴格的條件下運行。其主要有下面這幾個目的:
"嚴格模式"體現了Javascript更合理、更安全、更嚴謹的發展方向,包括IE 10在內的主流瀏覽器,都已經支持它。
一樣的代碼,在非嚴格模式下能夠運行,可是嚴格模式下可能將不能運行。
<script>
"use strict" console.log("已經進入嚴格模式"); </script> 複製代碼
<script>
"use strict" a = 10;//報錯 由於 a沒有被var 聲明 //Uncaught ReferenceError: a is not defined; 引用錯誤: a 沒有被聲明 </script> 複製代碼
<script>
"use strict" // console.log("已經進入嚴格模式"); function a(){ this.b = 10; //報錯 , 由於this指向了window對象; //Uncaught TypeError: Cannot set property 'b' of undefined; 類型錯誤 : 不能給undefined設置屬性b; } window.a(); </script> 複製代碼
<script>
"use strict"; function a(b,b,c){ //報錯 console.log(b,b,c); // 正常模式下 2,2,3 // Uncaught SyntaxError: Duplicate parameter name not allowed in this context ;語法錯誤:在此上下文中不容許重複的參數名稱 } a(1,2,3) </script> 複製代碼
arguments對象不容許被動態改變;
<script>
function fn1(a) { a = 2; return [a, arguments[0]]; } console.log(fn1(1)); // 正常模式爲[2,2] function fn2(a) { "use strict"; a = 2; return [a, arguments[0]]; } console.log(fn2(1)); // 嚴格模式爲[2,1] </script> 複製代碼
arguments對象不容許被自調用
<script>
"use strict"; var f = function() { return arguments.callee; }; f(); // 報錯 //Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them //類型錯誤:「caller 」,「arguments.callee 」,不能在嚴格模式中使用; //caller返回調用當前函數的函數的引用 (正在執行的函數的屬性) // callee返回正在執行的函數自己的引用 (arguments的屬性) </script> 複製代碼
this是js的關鍵字,他是根據執行上下文(執行環境)動態指向當前調用的對象; 誰調用,就指誰;
call()、apply()、bind() 能夠改變this的指向
js語言中一切皆爲對象,好比數字、字符串、數組、Math、Object、函數
js中對象的本質:屬性和方法的集合(無序,因此對象沒有length屬性)。
用官方一點的語言來解釋對象:
什麼是對象,其實就是一種類型,即引用類型。而對象的值就是引用類型的實例。在 ECMAScript 中引用類型是一種數據結構,用於將數據和功能組織在一塊兒。它也常被稱作爲類,但 ECMAScript6之前卻沒有這種東西。雖然 ECMAScript 是一門面向對象的語言,卻不具有傳統面嚮對象語言所支持的類等基本結構。
封裝、繼承、多態
一、寫對象
二、用對象
把一些相關的對象和屬性放到一塊兒,用一個變量抽象出來,那麼這就完成了這個對象的封裝
子承父業
子對象可使用父對象的一些屬性和方法
重載,重寫
重載就是根據不一樣的參數類型,參數個數實現不一樣的功能
重寫就是父類的方法很差用,我本身從新定義一個方法名相同的不一樣方法
var obj = { 鍵值對 key:value } 複製代碼
var obj = new Object() 複製代碼
function Person(name,age,job){
this.name= name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); } } var person1 = new Person('monkey',30,'web'); var person2 = new Person('zhu',25,'h5'); 複製代碼
工廠模式抽象了建立具體對象的過程。因爲在ECMAScript中沒法建立類,開發人員就發明了一種函數,用函數來封裝以特定接口建立對象的細節,以下面的例子:
function createPerson(name,age,job){
var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function(){ alert(this.name); } return o; } var person1 = createPerson('monkey',30,'web'); var person2 = createPerson('zhu',25,'h5'); 複製代碼
class Point {
constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } } 複製代碼
字符串的兩種建立方式(常量和構造函數),經常使用api有:
Math的經常使用屬性有:
經常使用api有:
經常使用api有:
上學時,班上的同窗會進行分組,以下圖,一豎排是一組
一列就是一個數組,一個數組裏面有不少個元素(多個同窗),由於js是弱類型語言,因此數組也是弱類型,同一個數組變量裏能夠有各類不一樣類型的元素。
var arr = [];
複製代碼
var arr = new Array(); //構造函數的方式 var arr = new Array(10);//一個參數指數組長度爲10 var arr = new Array(10,20,30);//多個參數指定義數組元素 複製代碼
ES5新增數組方法
判斷一個元素是否存在於數組中,若不存在返回-1,若存在就返回它第一次出現的位置
lastIndexOf() 方法可返回一個指定的字符串值最後出現的位置,在一個字符串中的指定位置從後向前搜索
循環遍歷數組中的每個元素,這個函數包含三個形參,分別爲:item, index, array, 用不到時能夠不寫
返回一個新數組,新數組是原數組的映射,不改變原數組,新數組的元素值是每次函數return的返回值,若不寫return,接收的新數組的元素值將全爲空
過濾元素,返回一個新數組,新的數組由每次函數返回值爲true對應的元素組成; 原數組不受影響
return返回的值只要有一項爲true,最終的返回值就爲true,不會繼續遍歷後邊的元素,若沒有一項知足返回值爲true的,就返回false,原數組不受影響;
對數組的每一項執行給定的函數,假如該函數每一項都返回true,最後結果才爲true;只要有一項返回值爲false,最後結果就是false。且後邊的元素都不會再繼續執行函數;原數組不受影響
reduce() 方法接收一個函數做爲累加器,數組中的每一個值(從左到右)開始縮減,最終計算爲一個值。reduce() 能夠做爲一個高階函數,用於函數的 compose
reduce() 對於空數組是不會執行回調函數的
reduceRight() 方法的功能和 reduce() 功能是同樣的,不一樣的是 reduceRight() 從數組的末尾向前將數組中的數組項作累加。
reduceRight() 對於空數組是不會執行回調函數的
ES6新增數組方法
傳入一個回調函數,找到數組中符合當前搜索規則的第一個元素,返回它,而且終止搜索
傳入一個回調函數,找到數組中符合當前搜索規則的第一個元素,返回它的下標,而且終止搜索
用新元素替換掉數組內的元素,能夠指定替換下標範圍。
格式:arr.fill(value, start, end)
選擇數組的某個下標,從該位置開始複製數組元素,默認從0開始複製。也能夠指定要複製的元素範圍。
格式:arr.copyWithin(被替換的起始位置,選取替換值的起始位置,選取替換值的結束位置)
將相似數組的對象(array-like object)和可遍歷(iterable)的對象轉爲真正的數組
用於將一組值,轉換爲數組
返回迭代器:返回鍵值對
返回鍵值對的value
返回鍵值對的key
判斷數組中是否存在該元素,參數:查找的值、起始位置,能夠替換 ES5 時代的 indexOf 判斷方式。indexOf 判斷元素是否爲 NaN,會判斷錯誤。
塊級做用域:一種廣泛存在於各個語言中的做用域範圍;
三個點號,功能是把數組或類數組對象展開成一系列用逗號隔開的值
var foo = function(a, b, c) {
console.log(a); console.log(b); console.log(c); } var arr = [1, 2, 3]; //傳統寫法 foo(arr[0], arr[1], arr[2]); //使用擴展運算符 foo(...arr); //1 //2 //3 複製代碼
rest運算符也是三個點號,不過其功能與擴展運算符剛好相反,把逗號隔開的值序列組合成一個數組
//主要用於不定參數,因此ES6開始能夠再也不使用arguments對象
var bar = function(a, ...args) { console.log(a); console.log(args); } bar(1, 2, 3, 4); //1 //[ 2, 3, 4 ] 複製代碼
ES6中存在一種新的字符串, 這種字符串是 以 (波浪線上的那個字符 > 反引號)括起來表示的; 一般咱們想要拼接一個帶有標籤的字符串, 是用這樣的方式:
bianliang + " <strong>這是一個文字" + obj.name + "</strong> " + bianliang
複製代碼
可是有了ES6字符串一切都變得很是簡單了;
` ${bianliang} <strong>這是一個文字${obj.name}</strong>${bianliang} `
複製代碼
用 ${ } 擴住變量讓拼接變得很是容易;
原來的寫法
var test = function(x){
return x+2; } 複製代碼
使用箭頭函數:
var test = x =>x+2;
var 函數名 = 參數 => 運算規則; 複製代碼
箭頭函數this指向的固定化,並非由於箭頭函數內部有綁定this的機制,實際緣由是箭頭函數根本沒有本身的this,致使內部的this就是外層代碼塊的this。正是由於這個,因此箭頭函數也不能作構造函數。主要有兩個缺陷:
var [a,b,c] = [1,2,3];
var {a,b,c} = { a:1, b:2, c:3 } var username = "zhangsan"; var age = 18; var obj = {username,age}; 複製代碼
想當初設計JS的時候,因爲有SUN公司人員的參與 再加上當時如日中天的JAVA及其優秀的設計,才使得JS語法及內存設計跟JAVA會如此的接近。但JAVA不少優秀的內容,JS不知道爲了什麼目的並無引入,例如Set和Map集合
Set集合,本質上就是對數組的一種包裝 例如:
let imgs = new Set();
imgs.add(1); imgs.add(1); imgs.add(5); imgs.add("5"); imgs.add(new String("abc")); imgs.add(new String("abc")); // 打印的結果: 1 5 '5' 'abc' 'abc' 複製代碼
Set集合是默認去重複的,但前提是兩個添加的元素嚴格相等 因此5和"5"不相等,兩個new出來的字符串不相等
關於遍歷的方法 因爲Set集合本質上仍是一個map,所以會有如下幾種奇怪的遍歷方法
var imgs = new Set(['a','b','c']);
//根據KEY遍歷 for(let item of imgs.keys()){ console.log(item); } //a //b //c 複製代碼
//根據VALUE遍歷
for(let item of imgs.values()){ console.log(item); } //a //b //c 複製代碼
//根據KEY-VALUE遍歷
for(let item of imgs.entries()){ console.log(item); } //['a','a'] //['b','b'] //['c','c'] 複製代碼
//普通for...of循環(for...of跟for-in的區別很明顯,就是直接取值,而再也不取下標了)
for(let item of imgs){ console.log(item); } //a //b //c 複製代碼
SET集合沒有提供下標方式的訪問,所以只能使用for來遍歷。
// 下面展現了一種極爲精巧的數組去重的方法
var newarr = [...new Set(array)];
Map集合,即映射
let map = new Map();
map.set("S230", "張三"); map.set("S231", "李四"); map.set("S232", "王五"); 獲取某一個元素 map.get("s232"); //王五 複製代碼
//循環遍歷,配合解構賦值
for(let [key,value] of map){
console.log(key,value); } 複製代碼
BOM(Browser Object Model 瀏覽器對象模型),結構以下圖所示:
window是全局瀏覽器內置頂級對象,表示瀏覽器中打開的窗口(沒有應用於window對象的公開標準,不過全部瀏覽器都支持該對象)。
在客戶端 JavaScript 中,Window 對象是全局對象,全部的表達式都在當前的環境中計算。
也就是說,要引用當前窗口根本不須要特殊的語法,能夠把那個窗口的屬性做爲全局變量來使用。
例如,能夠只寫 document,而沒必要寫 window.document。
一樣,能夠把當前窗口對象的方法看成函數來使用,如只寫 alert(),而沒必要寫 Window.alert()。
除了上面列出的屬性和方法,Window 對象還實現了核心 JavaScript 所定義的全部全局屬性和方法。
全局變量默認是掛在window下的,例如:
var a = 123; alert(window.a)//123 複製代碼
location:
通常狀況下給reload()傳遞一個true,讓他刷新,並不使用緩存。緩存的東西通常爲js文件,css文件等。用這個方法可讓本身不能動的頁面動起來了。刷新當前頁面。
window.navigator:
以上屬性已經在逐漸被拋棄了。
一個新的屬性將替代這些屬性。
navigator.userAgent 返回瀏覽器信息(可用此屬性判斷當前瀏覽器)
判斷當前瀏覽器類型的,示例:
function isBrowser() {
var userAgent = navigator.userAgent; //微信內置瀏覽器 if(userAgent.match(/MicroMessenger/i) == 'MicroMessenger') { return "MicroMessenger"; } //QQ內置瀏覽器 else if(userAgent.match(/QQ/i) == 'QQ') { return "QQ"; } //Chrome else if(userAgent.match(/Chrome/i) == 'Chrome') { return "Chrome"; } //Opera else if(userAgent.match(/Opera/i) == 'Opera') { return "Opera"; } //Firefox else if(userAgent.match(/Firefox/i) == 'Firefox') { return "Firefox"; } //Safari else if(userAgent.match(/Safari/i) == 'Safari') { return "Safari"; } //IE else if(!!window.ActiveXObject || "ActiveXObject" in window) { return "IE"; } else { return "未定義:"+userAgent; } } 複製代碼
history:
screen: 屏幕
window下的彈框方法:
DOM(Document Object Model 文檔對象模型),DOM定義了表示和修改文檔所需的對象、行爲和屬性,以及這些對象之間的關係。
獲得的是一個集合(不止一個,是一堆)
不是全部的標籤都有name值,低版本的瀏覽器會有兼容問題
IE8如下不能用
歷史好文推薦:
一、【萬字長文】史上最強css、html總結~看完漲薪再也不是夢
我是monkeysoft,你的【三連】就是monkeysoft創做的最大動力,若是本篇文章有任何錯誤和建議,歡迎你們留言!
文章持續更新,能夠微信搜索 【小猴子的web成長之路】關注公衆號第一時間閱讀,關注以後後臺回覆知識體系,更可領取小編精心準備的前端知識體系,將來學習再也不迷茫,更可加入技術羣交流討論。
本文使用 mdnice 排版