答案是確定的,那爲何不是[1,2,3]呢?javascript
首先看看官網上:php
paserInt的用法css
parseInt() 函數解析一個字符串參數,經過基數解析,返回一個整數或者NANhtml
parseInt() 的兩個參數分別是string和radix前端
string就是要解析的字符串,radix就是基數java
注意:node
map 遍歷數組,將數組中的每個元素調用定義的回調函數,返回包含結果的數組git
map()的第一個參數是回調函數,回調函數的三個參數分別是currentValue/index/arrgithub
currentValue是當前值,index當前值的索引,arr當前元素屬於的數組對象web
那麼回到這道題中,['1','2','3'].map(parseInt)就能夠等於
['1','2','3'].map(function('1',0)),
['1','2','3'].map(function('2',1)),
['1','2','3'].map(function('3',2))
接着
parseInt('1',0),
parseInt('2',1),
parseInt('3',2)
那麼,第一個字符串‘1’基於基數0也就是10進制返回值是1
第二個的基數是1小於2,返回值爲NAN
第三個中3是沒有2進制的,返回值爲NAN
function part(fn) {
return (...rest) => {
return fn.call(this, rest[0])
}
}
let a = ['1', '2', '3']
a.map(part(parseInt))
// [1, 2, 3]
複製代碼
爲何加個函數就返回沒問題了呢
function part(fn) {
return (...rest) => {
// console.log('rest', rest)
// rest (3) ["1", 0, Array(3)]
// rest (3) ["2", 1, Array(3)]
// rest (3) ["3", 2, Array(3)]
// console.log('rest[0]', rest[0])
// rest 1
// rest 2
// rest 3
// console.log(fn)
// parseInt() { [native code] }
// console.log('fn.call(this, rest[0])', fn.call(this, rest[0]))
//fn.call(this, rest[0]) 1
//fn.call(this, rest[0]) 2
//fn.call(this, rest[0]) 3
return fn.call(this, rest[0])
}
}
let a = ['1', '2', '3']
a.map(part(parseInt))
// [1, 2, 3]
複製代碼
...rest
獲取所有參數,即restparseInt()
函數call
繼承rest[0]
,執行函數就簡化爲parserInt('1'),parserInt('2'),parserInt('3')
爲何["1","2","3"].map(parseInt) 返回[1,NaN,NaN]?
防抖(debounce) 所謂防抖,就是指觸發事件後在n秒內函數只能執行一次,若是在n秒內又觸發了事件,則會從新計算函數執行時間。 防抖函數分爲非當即執行版和當即執行版。
function debounce(func, wait) {
let timeout
return function () {
let context = this
let args = arguments
if (timeout) clearTimeout(timeout)
timeout = setTimeout(() => {
func.apply(context, args)
}, wait)
}
}
複製代碼
背景:產生事件時,首先執行當即執行函數setTimeout。 當鼠標移動時,會產生setTimeout,每移動一次就timeout增長一次, 當timeout有值時,就銷燬定時器。若是中止移動,就不觸發定時器, 那麼timeout沒有值,那麼就執行加一操做。
獲取this和參數,爲了讓debounce函數最終返回的函數this指向不變以及依舊能接受參數。
完整版:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style> * { margin: 0; padding: 0; } #con { height: 100%; width: 100%; position: absolute; line-height: 600px; text-align: center; color: #ff0000; background-color: #ffff00; font-size: 100px; } </style>
</head>
<body>
<div id="con">
</div>
<script> let num = 1 let con = document.getElementById('con') function count() { con.innerHTML = num++ } function debounce(func, wait) { let timeout return function () { let context = this let args = arguments if (timeout) clearTimeout(timeout) timeout = setTimeout(() => { func.apply(context, args) }, wait) } } con.onmousemove = debounce(count, 1000) </script>
</body>
</html>
複製代碼
function debounce(func, wait) {
let timeout
return function () {
let context = this
let args = arguments
if (timeout) clearTimeout(timeout)
console.log('timeout',timeout)
let callNow = !timeout
timeout = setTimeout(() => {
timeout = null
}, wait)
if (callNow) func.apply(context, args)
}
}
複製代碼
當鼠標移動觸發事件,進入debounce方法中。當執行setTimeout方法時,timeout爲null,等一秒後再執行。在回到context/args賦值,若是此時timeout爲null則不清除定時器。 而且callNow爲ture,callNow爲ture,那麼執行加一操做。
完整版本:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style> * { margin: 0; padding: 0; } #con { height: 100%; width: 100%; position: absolute; line-height: 600px; text-align: center; color: #ff0000; background-color: #ffff00; font-size: 100px; } </style>
</head>
<body>
<div id="con">
</div>
<script> let num = 1 let con = document.getElementById('con') function count() { con.innerHTML = num++ } function debounce(func, wait) { let timeout return function () { let context = this let args = arguments if (timeout) clearTimeout(timeout) let callNow = !timeout timeout = setTimeout(() => { timeout = null }, wait) if (callNow) func.apply(context, args) } } con.onmousemove = debounce(count, 1000) </script>
</body>
</html>
複製代碼
須要當即執行,則加上第三個參數,不然不加。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style> * { margin: 0; padding: 0; } #con { height: 100%; width: 100%; position: absolute; line-height: 600px; text-align: center; color: #ff0000; background-color: #ffff00; font-size: 100px; } </style>
</head>
<body>
<div id="con">
</div>
<script> let num = 1 let con = document.getElementById('con') function count() { con.innerHTML = num++ } function debounce(func, wait, immediate) { let timeout return function () { let context = this let args = arguments if (timeout) clearTimeout(timeout) if (immediate) { let callNow = !timeout timeout = setTimeout(() => { timeout = null }, wait) if (callNow) func.apply(context, args) } else { timeout = setTimeout(() => { func.apply(context, args) }, wait) } } } con.onmousemove = debounce(count, 1000) </script>
</body>
</html>
複製代碼
window.addEventListener('resize', debounce(handleResize, 200));
複製代碼
debounce(fetchSelectData, 1000);
複製代碼
debounce(validator, 1000);
複製代碼
連續觸發事件,可是在n秒中只執行一次。節流會稀釋函數的執行頻率。
對於節流,通常有兩種方式能夠實現,分別是時間戳版和定時器版。 時間戳版:
function throttle(func, wait) {
var previous = 0
return function () {
let now = Date.now()
let context = this
let args = arguments
if (now - previous > wait) {
func.apply(context, args)
previous = now
}
}
}
複製代碼
在持續觸發事件過程當中,函數會當即執行,而且每1秒執行一次。
當時間每過去n秒後,執行加一事件。 完整版
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style> * { margin: 0; padding: 0; } #con { height: 100%; width: 100%; position: absolute; line-height: 600px; text-align: center; color: #ff0000; background-color: #ffff00; font-size: 100px; } </style>
</head>
<body>
<div id="con">
</div>
<script> let num = 1 let con = document.getElementById('con') function count() { con.innerHTML = num++ } function throttle(func, wait) { var previous = 0 return function () { let now = Date.now() let context = this let args = arguments if (now - previous > wait) { func.apply(context, args) previous = now } } } con.onmousemove = throttle(count, 1000) </script>
</body>
</html>
複製代碼
定時器版:
function throttle(func, wait) {
let timeout
return function () {
let context = this
let args = arguments
if (!timeout) {
timeout = setTimeout(() => {
timeout = null
func.apply(context, args)
}, wait)
}
}
}
複製代碼
持續觸發事件時,每當n秒後執行一次,timeout設爲空。當爲空又開始執行。
在持續觸發事件的過程當中,函數不會當即執行,而且每 1s 執行一次,在中止觸發事件後,函數還會再執行一次。 咱們應該能夠很容易的發現,其實時間戳版和定時器版的節流函數的區別就是,時間戳版的函數觸發是在時間段內開始的時候,而定時器版的函數觸發是在時間段內結束的時候。
完整版:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style> * { margin: 0; padding: 0; } #con { height: 100%; width: 100%; position: absolute; line-height: 600px; text-align: center; color: #ff0000; background-color: #ffff00; font-size: 100px; } </style>
</head>
<body>
<div id="con">
</div>
<script> let num = 1 let con = document.getElementById('con') function count() { con.innerHTML = num++ } function throttle(func, wait) { let timeout return function () { let context = this let args = arguments if (!timeout) { timeout = setTimeout(() => { timeout = null func.apply(context, args) }, wait) } } } con.onmousemove = throttle(count, 1000) </script>
</body>
</html>
複製代碼
雙劍合璧版:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style> * { margin: 0; padding: 0; } #con { height: 100%; width: 100%; position: absolute; line-height: 600px; text-align: center; color: #ff0000; background-color: #ffff00; font-size: 100px; } </style>
</head>
<body>
<div id="con">
</div>
<script> let num = 1 let con = document.getElementById('con') function count() { con.innerHTML = num++ } function throttle(func, wait, type) { if (type === 1) { console.log('css') // 時間戳版: let previous = 0 return function () { let now = Date.now() let context = this let args = arguments if (now - previous > wait) { previous = now func.apply(context, args) } } } else if (type === 2) { // 定時器版: let timeout return function () { let context = this let args = arguments if (!timeout) { timeout = setTimeout(() => { timeout = null func.apply(context, args) }, wait) } } } } con.onmousemove = throttle(count, 1000, 2) </script>
</body>
</html>
複製代碼
ES6 新增的一種新的數據結構,相似於數組,但成員是惟一且無序的。 Set 自己是一種構造函數,用來生成 Set 數據結構。
new Set([iterable]);
複製代碼
Set 實例方法
操做方法 - add(value):至關 array 裏的 push,新增 - delete(vallue):刪除集合中 value - has(value):判斷集合是否存在 value - clear():清空集合
遍歷方法(遍歷順序爲插入順序) - keys():返回一個包含集合中全部鍵的迭代器 - values():返回一個包含集合中全部值的迭代器 - entries():返回一個包含 Set 對象中全部元素的鍵值對迭代器 - forEach(callback,this):用於對集合成員執行回調操做,若是提供了參數,回調中的 this 就是這個參數,沒有返回值
WeakSet 對象容許將弱引用對象儲存在一個集合中 與 Set 的區別:
前者只能存儲對象引用,不能存放值,而 Set 對象均可以
前者對象中存儲的對象值都是被弱引用的,即垃圾回收機制不考慮其對該對象的應用,若是沒有其餘的變量或屬性引用這個對象值,則這個對象將會被垃圾回收掉(不考慮改對象還存在於 WeakSet 中)。WeakSet 對象裏有多少哥成員元素,取決於垃圾回收機制有沒有運行,運行先後成員個數可能不一致,遍歷結束後,有的成員可能取不到了(被垃圾回收),實際上是沒法被遍歷的,也無法拿到它的全部元素
屬性
add(value):在 WeakSet 對象中添加一個元素 value
has(value):判斷 WeakSet 對象中是否包含 value
delete(value):刪除元素 value
clear():清空全部元素
集合和字典的區別:
任何具備 Iterator 接口且每一個成員都是一個雙元素的數組的數據結構均可以看成Map
構造函數的參數
若是讀取一個未知的鍵,則返回 undefined。
由上可知,Map 的鍵其實是跟內存地址綁定的,只要內存地址不同,就視爲兩個鍵。這就解決了同名屬性碰撞(clash)的問題,咱們擴展別人的庫的時候,若是使用對象做爲鍵名,就不用擔憂本身的屬性與原做者的屬性同名。
若是 Map 的鍵是一個簡單類型的值(數字、字符串、布爾值),則只要兩個值嚴格相等,Map 將其視爲一個鍵,好比 0 和-0 就是一個鍵,布爾值 true 和字符串 true 則是兩個不一樣的鍵。另外,undefined 和 null 也是兩個不一樣的鍵。雖然 NaN 不嚴格相等於自身,但 Map 將其視爲同一個鍵。
Map 的屬性及方法
操做方法:
遍歷方法
Map 結構轉爲數組結構,比較快速的方法是使用擴展運算符(...)。
與其餘數據結構的相互轉換
Map 轉 Array
Array 轉 Map
Map 轉 Object
由於 Object 的鍵名都爲字符串,而 Map 的鍵名爲對象,因此轉換的時候會把非字符串鍵名轉爲字符串鍵名。
Object 轉 Map
Map 轉 JSON
JSON 轉 Map
是一組鍵值對的集合,其中的鍵是弱引用對象,而值能夠是任意的。 注意,WeakMap 弱引用的只是鍵名,而不是鍵值。鍵值依然是正常引用。 WeakMap 中,每一個鍵對本身所引用對象的引用都是弱引用,在沒有其餘引用和該鍵引用同一對象,這個對象將會被垃圾回收(相應的 key 則變成無效的),因此,WeakMap 的 key 是不可枚舉的。
字符串、數字、布爾、數組、對象、null、undefined
typeof, instanceof, isArray()?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input id="show" style="width:300px;"/>
<script>
function getTime(){
var nowDate = new Date();
var year = nowDate.getFullYear();
var month = (nowDate.getMonth() + 1) > 10 ? nowDate.getMonth() + 1 : '0' + (nowDate.getMonth() + 1);
var day = nowDate.getDate() > 10 ? nowDate.getDate() : '0' + nowDate.getDate();
var hour = nowDate.getHours() > 10 ? nowDate.getHours() : (nowDate.getHours() == 0 ? 24 : '0' + nowDate.getHours());
var minutes = nowDate.getMinutes() > 10 ? nowDate.getMinutes() : '0' + nowDate.getMinutes();
var seconds = nowDate.getSeconds() > 10 ? nowDate.getSeconds() : '0' + nowDate.getSeconds();
var str= year +"-" + month + "-" + day + " " + hour + ":" + minutes + ":" + seconds;
document.getElementById("show").value = str;
}
window.setInterval("getTime()", 1000);
</script>
</body>
</html>
複製代碼
顯示:object.style.display="block";
隱藏:object.style.display="none";
複製代碼
html的元素的事件就只有組件自帶的的那麼幾個,
如onclick,onmousedown等等都是調用腳本執行
方法:
1. 在組件上直接激發事件
2. 在頁面加載的時候就調用腳本激發組件的某個事件
3. 在後臺利用後臺代碼強行執行組件的事件。
或:
4. 爲HTML元素的事件屬性賦值
5. 在JS中使用el.on*** = function() {…}
6. 使用DOM2的添加事件的方法 addEventListener或attachEvent
複製代碼
\n alert("text\ntext");
alert("再打個招呼。這裏演示了" + "\n" + "如何在消息框中添加換行。")
複製代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script> var str = "abcdefgaddda"; var obj = {}; // 每一個字符出現次數 for (let i = 0; i < str.length; i++) { var key = str[i]; typeof obj[key] === 'undefined' ? obj[key] = 1 : obj[key]++ } var max = -1; var max_key = key; // 排序 for (let key in obj) { if (max < obj[key]) { max = obj[key]; max_key = key; } } document.write("字符:" + max_key + ",出現次數最多爲:" + max + "次") </script>
</body>
</html>
複製代碼
var reg = /^[a-zA-Z][a-zA-Z_0-9]{4,19}$/
console.log(reg.test("11a__a1a__a1a__a1a__"))
複製代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script> function parseQueryString(url) { var result = {}; var arr = url.split("?"); if (arr.length <= 1) { return result; } else { arr = arr[1].split("&"); arr.forEach(item => { let a = item.split('=') result[a[0]] = a[1] }) return result; } } var url = "http://witmax.cn/index.php?key0=0&key1=1&key2=2"; var ps = parseQueryString(url); console.log(ps) </script>
</body>
</html>
複製代碼
在頁面中有以下html:
<div id="field">
<input type="text" value="User Name"/>
</div><span class="red"></span>
複製代碼
要求用閉包方式寫一個JS從文本框中取出值並在標籤span中顯示出來。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="firld">
<input type="text" value="qiufeihong"/>
</div>
<span class="red"></span>
<script> var result = (function () { var value = document.getElementById("firld").children[0].value; var all = document.getElementsByTagName("span"); for (let i = 0; i < all.length; i++) { all[i].innerHTML = value; } })(); </script>
</body>
</html>
複製代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> .tit { position: absolute; width: 100px; height: 100px; background: red; } </style>
</head>
<body>
<div id="box" class="tit"></div>
<script> window.onscroll = window.onresize = window.onload = () => { var getDiv = document.getElementById('box'); var scrollTop = document.documentElement.scrollTop || document.body.scrollTop; getDiv.style.left = document.documentElement.clientWidth - getDiv.offsetWidth + 'px'; getDiv.style.top = document.documentElement.clientHeight - getDiv.offsetHeight + scrollTop + 'px'; } </script>
</body>
</html>
複製代碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style> .tit { display: block; width: 100px; height: 100px; background: yellow; } </style>
</head>
<body>
<div id="box" class="tit">div</div>
<p class="tit">p</p>
<a class="tit">a</a>
<script> function mouseBorder(t) { var c = t.childNodes for (let i = 0; i < c.length; i++) { var d = c[i]; if (d.nodeType == 1) { d.onmouseover = function () { this.style.border = '1px solid red' } d.onmouseout = function () { this.style.border = '' } mouseBorder(d); } } } mouseBorder(document.body); </script>
</body>
</html>
複製代碼
String,Number,Boolean
Window:
方法:setInterval,setTimeout,clearInterval,clearTimeout,alert,confirm,open
屬性:name,parent,screenLeft,screenTop,self,top,status
Document
方法:createElement,execCommand,getElementById,getElementsByName,getElementByTagName,write,writeln
屬性:cookie,doctype,domain,documentElement,readyState,URL,
複製代碼
不反對用Ext.ux.clone,可是最好仍是遞歸
function cloneObject(o) {
// 1. 是不是object,是否爲空
if (!o || 'object' !== typeof o) {
return o;
}
// 2. 判斷其是數組仍是對象,並建立新的對象或數組
var c = 'function' === typeof o.pop ? [] : {};
// 3. 遍歷對象或數組
for (let p in o) {
let v = o[p];
v && 'object' === typeof v ? c[p] = cloneObject(v) : c[p] = v
}
return c;
}
a = {
'name': 'qiufeihong'
}
b = cloneObject(a)
a.name = 'youyuxi'
console.log('a', a)
console.log('b', b)
複製代碼
Ele.className = 「***」; //***在css中定義,形式以下:.*** {…}
A.prototype.B = C;
A是某個構造函數的名字
B是這個構造函數的屬性
C是想要定義的屬性的值
複製代碼
Ajax是多種技術組合起來的一種瀏覽器和服務器交互技術,
基本思想是容許一個互聯網瀏覽器向一個遠程頁面/服務作異步的http調用,
而且用收到的數據來更新一個當前web頁面而沒必要刷新整個頁面。
該技術可以改進客戶端的體驗。包含的技術:
XHTML:對應W3C的XHTML規範,目前是XHTML1.0。
CSS:對應W3C的CSS規範,目前是CSS2.0
DOM:這裏的DOM主要是指HTML DOM,XML DOM包括在下面的XML中
JavaScript:對應於ECMA的ECMAScript規範
XML:對應W3C的XML DOM、XSLT、XPath等等規範
XMLHttpRequest:對應WhatWG的Web Applications1.0規範(http://whatwg.org/specs/web-apps/current-work/)
AJAX交互模型
同步:腳本會停留並等待服務器發送回覆而後再繼續
異步:腳本容許頁面繼續其進程並處理可能的回覆
跨域問題簡單的理解就是由於JS同源策略的限制,a.com域名下的JS沒法操做b.com或c.a.com下的對象,具體場景以下:
PS:(1)若是是端口或者協議形成的跨域問題前端是無能爲力的
(2) 在跨域問題上,域僅僅經過URL的首部來識別而不會嘗試判斷相同的IP地址對應的域或者兩個域是否對應一個IP
前端對於跨域的解決辦法:
(1) document.domain+iframe
(2) 動態建立script標籤
複製代碼
默認狀況javascript是同步加載的,也就是javascript的加載時阻塞的,後面的元素要等待javascript加載完畢後才能進行再加載,對於一些意義不是很大的javascript,若是放在頁頭會致使加載很慢的話,是會嚴重影響用戶體驗的。
(1) defer,只支持IE
defer屬性的定義和用法(我摘自w3school網站)
defer 屬性規定是否對腳本執行進行延遲,直到頁面加載爲止。
有的 javascript 腳本 document.write 方法來建立當前的文檔內容,其餘腳本就不必定是了。
若是您的腳本不會改變文檔的內容,可將 defer 屬性加入到
(2) async:
async的定義和用法(是HTML5的屬性)
async 屬性規定一旦腳本可用,則會異步執行。
(3) 建立script,插入到DOM中,加載完畢後callBack,見代碼:
複製代碼 代碼以下:
function loadScript(url, callback){
var script = document.createElement_x("script")
script.type = "text/javascript";
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" ||
script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others: Firefox, Safari, Chrome, and Opera
script.onload = function(){
callback();
};
}
script.src = url;
document.body.appendChild(script);
}
複製代碼
註釋:有多種執行外部腳本的方法: •async 屬性僅適用於外部腳本(只有在使用 src 屬性時)。 •若是 async="async":腳本相對於頁面的其他部分異步地執行(當頁面繼續進行解析時,腳本將被執行) •若是不使用 async 且 defer="defer":腳本將在頁面完成解析時執行 •若是既不使用 async 也不使用 defer:在瀏覽器繼續解析頁面以前,當即讀取並執行腳本
有關連接:異步加載js的幾種方式
Navigator 對象
navigator.appName 保存瀏覽器類型
navigator.appVersion 存有瀏覽器的版本信息
navigator.userAgent 用戶代理
複製代碼
最後,別忘了給這個項目點一個star哦,謝謝支持。
一個學習編程技術的公衆號。天天推送高質量的優秀博文、開源項目、實用工具、面試技巧、編程學習資源等等。目標是作到我的技術與公衆號一塊兒成長。歡迎你們關注,一塊兒進步,走向全棧大佬的修煉之路