function type_fn(a){ let result; if(typeof a == 'object'){ result = (a instanceof Array)?'Array':'object' }else{ result = typeof a } return result } 說明:鑑於 數組和對象和null的typeof都是object 因此基於typeof 另外須要instanceof判斷區分 //補充 也能夠用:Object.prototype.toString.call(a).slice(8,-1)
function Class(){ this.slogan = function(){ console.log('我來自班級1'); } } function Classmate(name){ this.name = function(){ console.log('我是'+name) } } Classmate.prototype = new Class(); //實例化 var peo1 = new Classmate('jerry'); peo1.name(); //我是jerry peo1.slogan(); //我來自班級1
建立一個新的對象 this指向新的對象 對this賦值 執行代碼 返回this
/** * 原型鏈繼承的例子 * 功能: 1.獲取元素改變或者獲取他的innerhtml。 * 2.添加事件。 */ //構造函數 function Elem(id){ this.elem = document.getElementById(id); }; //在其原型上添加方法 Elem.prototype.html = function(val){ var elem=this.elem; if(val){ elem.innerHTML = val; return this; //鏈式調用 }else{ return elem.innerHTML; } } Elem.prototype.on = function(type,fn){ var elem=this.elem; elem.addEventListener(type,fn); return this; } var div=new Elem('app'); div.html(`<h1>你好javascript</h1>`).on('click',function(){ alert('我是天使') }) 原文連接:https://blog.csdn.net/qq_24675001/article/details/82054443
當JavaScript執行過程進入新函數時,這個函數內被聲明的全部變量都會被移動導到函數最開始的地方。這種現象叫作提高。且被提高的只有變量的聲明。javascript
函數執行時會先建立當前的上下文環境,其中這兩點會產生「變量提高」的效果php
做爲構造函數時的執行 指向構造函數的對象css
做爲對象屬性時的執行 指向對象html
做爲普通函數時的執行 指向window前端
call bind apply 從新把this指向新對象java
var i for (i = 0; i < 10; i++) { (function (i) { var a = document.createElement('a') a.innerHTML = i + '<br>' a.addEventListener('click', function (e) { e.preventDefault() alert(i) }) document.body.appendChild(a) })(i) }
* 自由變量 * 做用域鏈,即自由變量的查找 * 閉包的兩個場景
// 閉包實際應用中主要用於封裝變量,收斂權限 // 即把變量隱藏起來,不讓外面拿到和修改 function isFirstLoad() { var _list = [] return function (id) { if (_list.indexOf(id) >= 0) { return false } else { _list.push(id) return true } } } // 使用 var firstLoad = isFirstLoad() firstLoad(10) // true firstLoad(10) // false firstLoad(20) // true // 在 isFirstLoad 函數外面,根本不可能修改掉 _list 的值
同步會阻塞代碼 而異步不會 alert 是同步 setTimeout 是異步 eg: console.log('1'); setTimeout(function(){ console.log('2'); },200) console.log('3'); ------------- console.log('1') alert('2') console.log('3');
jq源碼裏面利用了js程序的單線程 寫了setTimeout(function(){})來解決 等頁面加載完; ------------------ console.log(1); setTimeout(function(){ console.log(2) },0) console.log(3) setTimeout(function(){ console.log(4) },1000) console.log(5) >> 1 3 5 2 4
定時任務: setTimeout setInverval 網絡請求: ajax請求 動態<img>加載 事件綁定
function time(){ var date = new Date(); var year = date.getFullYear(); var month = date.getMonth()+1; var day = date.getDate(); return year+'-'+num_fn(month)+'-'+num_fn(day); } function num_fn(num){ return num>=10? num : '0'+num }
function randomAtr(){ return Math.floor(Math.random()*1000000000) //或者 //var num = Math.random()+''; //return num.slice(2,13) }
function forEach_fn(obj,fn){ var key; if(obj instanceof Array){ arr.forEach(function(item, index){ fn(index, item)//遍歷數組全部的元素 }) }else{ for(key in obj){ fn(key, obj[key]) } }
}ajax
DOM樹形結構json
建立型api:createElement
,createTextNode
,cloneNode
和createDocumentFragment
後端
頁面修改型API
修改頁面內容的api主要包括:appendChild
,insertBefore
,removeChild
,replaceChild
。api
節點查詢型API
document.getElementById
document.getElementsByTagName
document.getElementsByName
document.getElementsByClassName
document.querySelector和document.querySelectorAll:經過css選擇器來查找元素,注意選擇器要符合CSS選擇器的規則,使用的深度優先搜索來獲取元素
節點關係型api
1.父關係型api
2.子關係型api
3.兄弟關係型api
元素屬性型apisetAttribute
:根據名稱和值修改元素的特性eg:element.setAttribute(name, value); getAttribute
:返回指定的特性名相應的特性值,若是不存在,則返回null或空字符串.
property 只是一個JS對象的屬性的修改
Attribute 是對html標籤屬性的修改
navigator.userAgent 加正則匹配
href 完整的 URL。 protocol 當前 URL 的協議。 host 主機名和當前 URL 的端口號。 hostname 當前 URL 的主機名。 pathname 當前 URL 的路徑部分。 port 當前 URL 的端口號。 hash hash。從井號(#)開始)。 search 參數。從問號(?)開始的。
function bindEvent(elem,type,selector,fn){ if(fn == null){ fn = selector; selector = null; } elem.addEventListener(type,function(e){ var target; if(selector){//有代理 target = e.target; if(target.macthes(target)){ fn.call(target,e)//從新指定this 並傳參e } }else{//無代理 fn(e); } }) }
沿着DOM樹形結構,一層層網上冒泡, 一直到 最頂端或者出現阻止冒泡命令 e.stopPropagation(); 冒泡的應用 代理
事件委派
1.建立ajax對象
2.接收服務器
3.發送請求
4.接收返回值
var oAjax = new XMLHttpRequest(); oAjax.open("GET","text.json",false); oAjax.send(); oAjax.onreadystatechange(function(){ if(oAjax.readyState == 4){ if(oAjax.status == 200){ console.log(oAjax.responseText) } } })
0開頭
未初始化 尚未調用open()方法;1開頭
載入 已調用open()方法,正在發送請求2開頭
載入完成 send()方法完成,已收到所有響應內容3開頭
解析 正在解析響應內容4開頭
完成 響應內容解析完成,能夠再客戶端調用5開頭
服務器錯誤 1. 服務器請求頭修改 2. 重定向代理 3. jsonp
jsonp跨域 原生實現: <script> var script = document.createElement('script'); script.type = 'text/javascript'; // 傳參並指定回調執行函數爲onBack script.src = 'http://www.....:8080/login?user=admin&callback=onBack'; document.head.appendChild(script); // 回調執行函數 function onBack(res) { alert(JSON.stringify(res)); } </script>
get 安全性差 容量低 有緩存 經過url傳 通常用於獲取數據 post 安全性高 容量高 無緩存 通常用於用戶註冊
cookies
sessionStrorage
localStrorage
localStorage.setItem("saveData", JSON.stringify(setData) ); //存值 補充:存儲前先用JSON.stringify()將json對象轉字符串 localStorage.getItem("saveData」) //取值 補充:JSON.parse(ss) 將json字符串轉爲 json格式 localStorage.removeItem("saveData」);//刪值
瀏覽器根據DNS服務器獲得域名的IP地址 向這個IP的機器發送https/https請求 服務器收到、處理並返回請求 瀏覽器獲得返回內容
window.onload:頁面的所有資源加載完纔會執行,包括圖片、視頻等 DOMContentLoaded:DOM渲染完便可執行,此時圖片、視頻尚未加載完
性能優化: 多使用內存、緩存或其餘方法 減小cpu計算、減小網絡 加載資源優化: 1靜態資源的合併壓縮 2靜態資源緩存 3使用CDN讓資源加載更快 4使用SSR後端渲染,數據直接輸出到HTML中 渲染優化: 1.CSS放前面 JS放後面 2.懶加載(圖片懶加載、下拉加載更多) 3.減小DOM查詢,對DOM查詢作緩存 4.減小DOM操做,多個操做盡可能合併在一塊兒執行 5.事件節流 6.儘早執行操做(如DOMContentLoaded)
1 局部處理 meta標籤中的 viewport屬性 ,initial-scale 設置爲 1 rem 按照設計稿標準走,外加利用transfrome 的scale(0.5) 縮小一倍便可; 2 全局處理 meta標籤中的 viewport屬性 ,initial-scale 設置爲 0.5 rem 按照設計稿標準走便可
名字 | 特性說明 |
---|---|
var | 變量; 能重複聲明; 函數級; 頂層對象的屬性; 不限制修改 |
let | 變量; 不能重複聲明; 塊級; 不屬於頂層對象的屬性; 可修改 |
const | 聲明和賦值必須是同時進行; 常量; 不能重複聲明; 塊級; 不屬於頂層對象的屬性; "不"可修改[ 實際上並不是徹底不可修改。const聲明建立一個值的只讀引用,對於基本類型不可修改,但若是是複合類型時,只要不修改引用,修改裏面的值是能夠的 ]; |
代碼演示: console.log(k_name); //變量提高;輸出undefined var k_name = "jerry"; console.log(k_name);//輸出jerry console.log('1',k_age);//不會變量提高;在定義以前報錯不能用 let k_age = "12"; console.log('2',k_age); //const基礎類型時 const may_class = 3; may_class = 4;//基礎類型時 報錯 //const複雜類型時 const all_class = [1,2,3]; all_class[0] = 9; //不報錯 console.log(all_class);//修改爲功 》[9, 2, 3]
var url = "http://witmax.cn/index.php?key0=0&key1=1&key2=2"; // 返回url的拼接對象 function parseQueryString(argu) { var str = argu.split('?')[1]; var result = {}; var temp = str.split('&'); for (vari = 0; i < temp.length; i++) { var temp2 = temp[i].split('='); result[temp2[0]] = temp2[1]; } return result; //url上的所有參 } // 拓展一下 對頁面url操做, 只有一個參 那麼查找url上的參數並返回值, 若是有兩個參數查找更新或刪除參數 function urlSearch(argu ,newValue) { var str = window.location.search.slice(1); var result = {}; var temp = str.split('&'); for (vari = 0; i < temp.length; i++) { var temp2 = temp[i].split('='); result[temp2[0]] = temp2[1]; } return result; //url上的所有參 if (newValue !== undefined) { if (newValue !== null) { result[argu] = newValue;//更新值 }else { delete result[argu];//刪除值 } // 更新參數後從新拼接 並替換url的連接 var str = ''; for(k in ee){ str += (k + '=' + ee[k] + '&'); } str = str.replace(/&$/,''); // var newUrl = window.decodeURIComponent(argu.split('?')[0]+'?'+str); var newUrl = window.location.href.split('?')[0]+'?'+str; window.history.pushState(null, document.title,newUrl); // return newUrl; }else{ return result[argu]; } }
if([] == false){ alert(1)} //在比較前false轉成0 [].toString()轉成了空字符串 空字符串轉成0, ;因此true if({} == false){ alert(2)}//在比較前false轉成0, {}.toString()轉成"[object Object]" 不等 if([]){ alert(3)} //引用類型(數組 對象 函數)的比較並不是值的比較:兩個對象保含一樣的屬性及相同的值 它們是不相等的。 各個因此元素徹底相等的兩個數組也不相等。 if([1] == [1]){ alert(4)} if({x:1} == {x:1} ){ alert(4)}
引用類型的比較均是引用的比較:當且僅當它們引用同一個基對象時,它們才相等 eg:
var a = []; var b = a; //變量b引用同一個數組 b[0] = 1; console.log(b); // [1] console.log(a); // [1] a === b; //true: a和b引用同一個數據,所以它們相等 ###### 給定一個整數數組,找出其中兩個數相加等於目標值
var twoSum = function(nums, target) { var cbArr = []; for(var i = 0; i< nums.length; i++){ if(cbArr.indexOf(i) == -1){ //除去已經在結果裏面的 避免重複 for(var k = 0; k< nums.length; k++){ if((i !== k) && (nums[i]+ nums[k] == target)){ cbArr.push(i,k); } } } } return cbArr; };
eg: 輸入: s = "lrloseumgh", k = 6 輸出: "umghlrlose" var reverseLeftWords = function(s, n) { return s.slice(n).concat(s.slice(0,n)) };
function Foo(){ getName = function(){alert(1)}; return this; } Foo.getName = function(){alert(2)}; Foo.prototype.getName = function(){alert(3)}; var getName = function(){alert(4)}; function getName(){alert(5)}; Foo.getName(); getName(); Foo().getName(); getName(); new Foo().getName(); 答案---- //2 4 1 1 3
function fn(a) { console.log(a) var a = 123; console.log(a) function a() {} console.log(a) var b = function() { console.log('bb','1') } console.log(b) b(); function b() { console.log('bb','2') } } fn(1) -------------------------- a的分析: 進入fn 雖然帶參數a進去 可是 進到函數 1 最開始a有聲明式函數,會直接掛載在函數下,因此第一個打印是function; 2 第一個打印後立刻就給a賦值了123, 因此第二個打印是123; 3 下一行 a的聲明式函數比2執行還早 因此不影響 第三個打印是123; -------------------------- b的分析: 1 b無論屬於誰打印確定是function; 2 最開始b有聲明式函數,會直接掛載在函數下,而後var 從新賦值了b的函數 因此 輸出是 答案:function 123 123 function bb 1
var i= 10; function a(){ i = 20; console.log(i); // 20; for(var i=0; i<6;i++){ console.log(i) // 0-5 } console.log(this.i); //10 :window.i 外部環境不能訪問內部環境中的任何變量和函數 console.log(i); //6 : 當前的局部變量在循環時被賦值爲6 } a(); console.log(i) //10 :window.i 外部環境不能訪問內部環境中的任何變量和函數
想法:寫個閉包每次返回函數都帶參累加,知道參數沒有再也不執行函數 則返回累加的和。
先寫個暴力概念版 只要我寫得夠多就能'知足'題目要求:
function add(a){ let sum = a; return function count_fn1(b){ sum +=b; return function count_fn1(c){ sum +=c; return function count_fn1(d){ sum +=d; return sum; }; }; } } add(1)(2)(3)(4)//10 全然不顧靈活不靈活拓展不拓展~ 老子就是幹
不 咱們不能僅苟且的活着!要靈活要自由~
function add(a){ let sum = a; return function count_fn(b){ sum +=b; return count_fn(b); } } //改爲遞歸 是能夠靈活執行多少次函數達到累加。問題 輸出的也是函數 沒有把累計的值輸出出來呀!
這時咱們要了解一個知識點:當咱們直接對函數使用alert()
或console.log()
時,函數的toString()
方法會被調用。並且函數的toString()方法是能夠複寫的
最終版:
function add(x) { var sum = x; var tmp = function (y) { sum = sum + y; return tmp; }; tmp.toString = function () { return sum; }; return tmp; } console.log(add(1)(2)(3)); //6
(() => { let x, y try { throw new Error() } catch (x) { (x = 1), (y = 2) console.log(x) } console.log(x) console.log(y) })() 答案: 1 undefined 2; 分析: catch 代碼塊接收參數 x。當咱們傳遞參數時,這與以前定義的變量 x 不一樣 。這個 x 是屬於 catch 塊級做用域的且 默認了設置了等於1; 因此第一個打印1; 外面x依然沒賦值;因此第二個打印`undefined`; y最開始let聲明瞭,後面賦值了2,因此第二個打印2;
let person = { name: "Lydia" }; const members = [person]; person = null; console.log(members); 答案:[{ name: "Lydia" }]; 分析: 當設置兩個對象彼此相等時,它們會經過 引用進行交互。可是當將`引用從一個變量分配至另外一個變量時`,實際上是執行了 複製 操做。 因此它們的引用並不一樣
const settings = { username: "lydiahallie", level: 19, health: 90 }; const data = JSON.stringify(settings, ["level", "health"]); console.log(data); 答案:"{"level":19, "health":90}" 分析: [JSON.stringify(value[, replacer[, space]])](https://www.runoob.com/js/javascript-json-stringify.html)//老子還有第二第三個參數可傳哦。 // 參數一:轉換的值 // 參數二:替代者。用於轉換結果的函數或數組。 // 參數三:控制空格 JSON.stringify的第二個參數是 替代者(replacer). 替代者(replacer)能夠是個函數或數組,用以控制哪些值如何被轉換爲字符串。 若是替代者(replacer)是個 數組 ,那麼就只有包含在數組中的屬性將會被轉化爲字符串。在本例中,只有名爲"level" 和 "health" 的屬性被包括進來, "username"則被排除在外。 data 就等於 "{"level":19, "health":90}」.
懶加載: 圖片的懶加載作法 都是把連接存放在 data-src中,監聽onscroll時,一個個加載出來;
預加載:將全部所需的資源提早請求加載到本地,這樣後面在須要用到時就直接從緩存取資源。
實現預加載的幾種辦法:
//使用img標籤 <img src="http://pic26.nipic.com/20121213/6168183 0044449030002.jpg" style="display:none」/> ------------ //js 使用Image對象 <script src="./myPreload.js"></script> //myPreload.js文件 var image= new Image() image.src="http://pic26.nipic.com/20121213/6168183 004444903000 2.jpg" ------------- //使用PreloadJS庫 ------------- //使用XMLHttpRequest對象,雖然存在跨域問題,但會精細控制預加載過程 var xmlhttprequest=new XMLHttpRequest(); xmlhttprequest.onreadystatechange=callback; xmlhttprequest.onprogress=progressCallback; xmlhttprequest.open("GET","http://image.baidu.com/mouse,jpg",true); xmlhttprequest.send(); function callback(){ if(xmlhttprequest.readyState==4&& xmlhttprequest.status==200){ var responseText=xmlhttprequest.responseText; }else{ console.log("Request was unsuccessful:"+xmlhttprequest.status); } } function progressCallback(e){ e=e || event; if(e.lengthComputable){ console.log("Received"+e.loaded+"of"+e.total+"bytes") } }
1.break 跳出循環 2.continue 跳出本次循環,進入下次循環 3.return 停止跳出當前函數 4.throw 異常信息;停止程序拋出異常,可用於停止程序
定義:內存泄漏指任何對象在您再也不擁有或須要它以後仍然存在。
後果:變慢,崩潰,延遲大等:
哪些會形成:
dom
清空時,還存在引用避免策略
重繪:改變元素的樣式。例如寬高顏色。
迴流(重排):佈局和樣式都改變。
重排必定重繪,重繪不必定重排。
減小重繪和重排的方法:
DOM
查詢cssText
或者className
一次性改變屬性fragment
。