前端知識點之JavaScript系列1-20

  1. 爲何["1","2","3"].map(parseInt) 返回[1,NaN,NaN]

開始

Screenshot from 2019-04-18 09-48-49

答案是確定的,那爲何不是[1,2,3]呢?javascript

知識

首先看看官網上:php

paserInt的用法css

parseInt() 函數解析一個字符串參數,經過基數解析,返回一個整數或者NANhtml

parseInt() 的兩個參數分別是string和radix前端

string就是要解析的字符串,radix就是基數java

注意:node

  • 基數不在2-36之間,則返回值就是NAN

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]
複製代碼
  1. ...rest獲取所有參數,即rest
  2. 再獲取每一個參數中的索引爲0的值,即rest[0]
  3. fn就是parseInt()函數
  4. 接着fn用call繼承rest[0],執行函數就簡化爲parserInt('1'),parserInt('2'),parserInt('3')
  5. 最後返回的值就是[1,2,3]
參考文獻

爲何["1","2","3"].map(parseInt) 返回[1,NaN,NaN]?


  1. 手寫節流和防抖

防抖

防抖(debounce) 所謂防抖,就是指觸發事件後在n秒內函數只能執行一次,若是在n秒內又觸發了事件,則會從新計算函數執行時間。 防抖函數分爲非當即執行版和當即執行版。

  • 非當即執行:觸發事件後函數不會當即執行,而是在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>

複製代碼

在線預覽

  • 當即執行:觸發事件後函數會當即執行,而後n秒後不觸發事件才能繼續執行函數。
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));
複製代碼
  • 搜索框,輸入後1000毫秒搜索
debounce(fetchSelectData, 1000);
複製代碼
  • 表單驗證,輸入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>

複製代碼

  1. 介紹下Set和Map和WeakSet和WeakMap的區別

集合 Set

ES6 新增的一種新的數據結構,相似於數組,但成員是惟一且無序的。 Set 自己是一種構造函數,用來生成 Set 數據結構。

new Set([iterable]);
複製代碼

Screenshot from 2019-05-05 10-58-15

Screenshot from 2019-05-05 11-01-34

Set 對象存儲原始值或是對象引用的惟一值。 向 Set 加入值的時候,不會發生類型轉換,因此 1 和‘1’是兩個不一樣的值。Set 用‘Same-value-zero equality’算法來判斷兩個值是否不一樣,它相似於精確相等運算符(===),主要的區別是 NAN 等於自身,而精確相等運算符認爲 NaN 不等於自身。

Screenshot from 2019-05-05 11-09-15

  • Set 實例屬性
    • constructor:構造函數
    • size:元素數量

Screenshot from 2019-05-05 11-13-06

  • Set 實例方法

    • 操做方法 - add(value):至關 array 裏的 push,新增 - delete(vallue):刪除集合中 value - has(value):判斷集合是否存在 value - clear():清空集合

      Screenshot from 2019-05-05 11-18-25

      Screenshot from 2019-05-05 11-21-06

    • 遍歷方法(遍歷順序爲插入順序) - keys():返回一個包含集合中全部鍵的迭代器 - values():返回一個包含集合中全部值的迭代器 - entries():返回一個包含 Set 對象中全部元素的鍵值對迭代器 - forEach(callback,this):用於對集合成員執行回調操做,若是提供了參數,回調中的 this 就是這個參數,沒有返回值

      Screenshot from 2019-05-05 11-40-27

      Set 可默認遍歷,默認迭代器生成函數是 values() 方法

      Screenshot from 2019-05-05 11-45-00

      因此, Set 可使用 map、filter 方法

      Screenshot from 2019-05-05 11-47-40

      所以,Set 很容易實現交集(Intersect)、並集(Union)、差集(Difference)

      Screenshot from 2019-05-05 11-52-29

      差集仍是有問題的

WeakSet

WeakSet 對象容許將弱引用對象儲存在一個集合中 與 Set 的區別:

  • 前者只能存儲對象引用,不能存放值,而 Set 對象均可以

  • 前者對象中存儲的對象值都是被弱引用的,即垃圾回收機制不考慮其對該對象的應用,若是沒有其餘的變量或屬性引用這個對象值,則這個對象將會被垃圾回收掉(不考慮改對象還存在於 WeakSet 中)。WeakSet 對象裏有多少哥成員元素,取決於垃圾回收機制有沒有運行,運行先後成員個數可能不一致,遍歷結束後,有的成員可能取不到了(被垃圾回收),實際上是沒法被遍歷的,也無法拿到它的全部元素

  • 屬性

    • constructor:構造函數,任何一個具備 Iterable 接口的對象,均可以做參數

Screenshot from 2019-05-05 13-21-40

  • add(value):在 WeakSet 對象中添加一個元素 value

  • has(value):判斷 WeakSet 對象中是否包含 value

  • delete(value):刪除元素 value

  • clear():清空全部元素

    Screenshot from 2019-05-05 13-26-05

字典(Map)

集合和字典的區別:

  • 共同點:集合和字典能夠存儲不重複的值
  • 異點:集合是[value,value]的形式儲存元素,字典是[key,value]的形式儲存

Screenshot from 2019-05-05 13-32-53

任何具備 Iterator 接口且每一個成員都是一個雙元素的數組的數據結構均可以看成Map構造函數的參數

Screenshot from 2019-05-05 13-38-00

Screenshot from 2019-05-05 13-38-23

若是讀取一個未知的鍵,則返回 undefined。

Screenshot from 2019-05-05 13-40-12

注意,只有對同一個對象的引用,Map 結構纔將其視爲同一個鍵。這一點要很是當心。

Screenshot from 2019-05-05 13-42-57

Screenshot from 2019-05-05 13-43-03

上面代碼的 set 和 get 方法,表面是針對同一個鍵,但實際上這是兩個值,內存地址是不同的,所以 get 方法沒法讀取該鍵,返回 undefined。

由上可知,Map 的鍵其實是跟內存地址綁定的,只要內存地址不同,就視爲兩個鍵。這就解決了同名屬性碰撞(clash)的問題,咱們擴展別人的庫的時候,若是使用對象做爲鍵名,就不用擔憂本身的屬性與原做者的屬性同名。

若是 Map 的鍵是一個簡單類型的值(數字、字符串、布爾值),則只要兩個值嚴格相等,Map 將其視爲一個鍵,好比 0 和-0 就是一個鍵,布爾值 true 和字符串 true 則是兩個不一樣的鍵。另外,undefined 和 null 也是兩個不一樣的鍵。雖然 NaN 不嚴格相等於自身,但 Map 將其視爲同一個鍵。

Screenshot from 2019-05-05 13-48-31

Map 的屬性及方法

  • 屬性:
    • constructor:構造函數
    • size:返回字典中所包含的元素個數

Screenshot from 2019-05-05 13-50-59

  • 操做方法:

    • set(key, value):向字典中添加新元素
    • get(key):經過鍵查找特定的數值並返回
    • has(key):判斷字典中是否存在鍵 key
    • delete(key):經過鍵 key 從字典中移除對應的數據
    • clear():將這個字典中的全部元素刪除
  • 遍歷方法

    • Keys():將字典中包含的全部鍵名以迭代器形式返回
    • values():將字典中包含的全部數值以迭代器形式返回
    • entries():返回全部成員的迭代器
    • forEach():遍歷字典的全部成員

Screenshot from 2019-05-05 13-53-44

Map 結構的默認遍歷器接口(Symbol.iterator 屬性),就是 entries 方法。

Screenshot from 2019-05-05 13-55-01

Map 結構轉爲數組結構,比較快速的方法是使用擴展運算符(...)。

與其餘數據結構的相互轉換

  • Map 轉 Array

    Screenshot from 2019-05-05 13-57-58

  • Array 轉 Map

Screenshot from 2019-05-05 13-59-04

  • Map 轉 Object

    由於 Object 的鍵名都爲字符串,而 Map 的鍵名爲對象,因此轉換的時候會把非字符串鍵名轉爲字符串鍵名。

    Screenshot from 2019-05-05 14-05-29

  • Object 轉 Map

    Screenshot from 2019-05-05 14-06-19

  • Map 轉 JSON

    Screenshot from 2019-05-05 14-07-06

  • JSON 轉 Map

    Screenshot from 2019-05-05 14-09-41

WeakMap

是一組鍵值對的集合,其中的鍵是弱引用對象,而值能夠是任意的。 注意,WeakMap 弱引用的只是鍵名,而不是鍵值。鍵值依然是正常引用。 WeakMap 中,每一個鍵對本身所引用對象的引用都是弱引用,在沒有其餘引用和該鍵引用同一對象,這個對象將會被垃圾回收(相應的 key 則變成無效的),因此,WeakMap 的 key 是不可枚舉的。

  • 屬性:
    • constructor:構造函數
  • 方法:
    • has(key):判斷是否有 key 關聯對象
    • get(key):返回 key 關聯對象(沒有則則返回 undefined)
    • set(key):設置一組 key 關聯對象
    • delete(key):移除 key 的關聯對象
總結:
  • Set
    • 無序且不重複的
    • [value,value],鍵值和鍵名重複
    • 能夠遍歷,方法有:add、delete、has、clear
  • WeakSet
    • 成員都是對象
    • 成員都是弱引用,能夠被垃圾回收機制回收,能夠用來保存 DOM 節點,不容易形成內存泄漏
    • 不能遍歷,方法有:add、delete、has、clear
  • Map
    • 本質上是鍵值對的集合,字典
    • 能夠遍歷,方法:set、delete、has、get、clear
    • 能夠跟各類數據格式轉換
  • WeakMap
    • 只接受對象做爲鍵名(null 除外),不接受其餘類型的值做爲鍵名
    • 鍵名是弱引用,鍵值能夠是任意的,鍵名所指向的對象能夠被垃圾回收,此時鍵名是無效的
    • 不能遍歷,方法有:get、set、has、delete

  1. JavaScript包括哪些數據類型請分別編寫3種以上類型的判斷函數如isString

字符串、數字、布爾、數組、對象、null、undefined

typeof, instanceof, isArray()?


  1. 編寫一個JavaScript函數,實時顯示當前時間,格式‘年-月-日 時:分:秒’?

<!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>
複製代碼

  1. 如何顯示/隱藏一個DOM元素?

顯示:object.style.display="block";
隱藏:object.style.display="none";
複製代碼

  1. 如何添加html元素的事件處理,有幾種方法

html的元素的事件就只有組件自帶的的那麼幾個,
如onclick,onmousedown等等都是調用腳本執行

方法:
1. 在組件上直接激發事件
2. 在頁面加載的時候就調用腳本激發組件的某個事件
3. 在後臺利用後臺代碼強行執行組件的事件。
  或:
4. 爲HTML元素的事件屬性賦值 
5. 在JS中使用el.on*** = function() {…}
6. 使用DOM2的添加事件的方法 addEventListener或attachEvent
複製代碼

  1. 如何控制alert中的換行

\n alert("text\ntext");
alert("再打個招呼。這裏演示了" + "\n" + "如何在消息框中添加換行。")
複製代碼

  1. 判斷一個字符串中出現次數最多的字符,統計這個次數。

<!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>
複製代碼

  1. 判斷字符串是不是這樣組成的,第一個必須是字母,後面能夠是字母、數字、下劃線,總長度爲5-20

var reg = /^[a-zA-Z][a-zA-Z_0-9]{4,19}$/
console.log(reg.test("11a__a1a__a1a__a1a__"))

複製代碼

  1. 請編寫一個JavaScript函數parseQueryString,他的用途是把URL參數解析爲一個對象,如:var url=「http://witmax.cn/index.php?key0=0&key1=1&key2=2」

<!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>


複製代碼

  1. 在頁面中有以下html要求用閉包方式寫一個JS從文本框中取出值並在標籤span中顯示出來

在頁面中有以下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>
複製代碼

在線預覽


  1. 在IE6.0下面是不支持position:fixed的,請寫一個JS使用
    固定在頁面的右下角。

前提知識
  1. window.onscroll 爲當前頁面的頁面滾動事件添加事件處理函數.
  2. window.onresize 用來獲取或設置當前窗口的resize事件的事件處理函數
  3. window.onload 用於在網頁加載完畢後馬上執行的操做,即當 HTML 文檔加載完畢後,馬上執行某個方法。
  4. document.documentElement.scrollTop 獲取滾動條位置
  5. document.documentElement.clientWidth 獲取瀏覽器窗口文檔顯示區域的寬度,不包括滾動條。
  6. document.documentElement.clientHeight 獲取瀏覽器窗口文檔顯示區域的高度,不包括滾動條。
  7. document.documentElement.offsetWidth 獲取DOM文檔的根節點html元素對象的寬度,即offsetWidth=width+padding+border,不包括margin。
  8. document.documentElement.offsetHeight 獲取DOM文檔的根節點html元素對象的高度,即offsetHeight=height+padding+border,不包括margin。
解析
  1. 當前頁面的頁面滾動、更改當前頁面的大小和加載完成時執行下面方法
  2. 獲取div,獲取滾動條位置
  3. 瀏覽器窗口的寬度減去div的寬度爲div的left屬性的值
  4. 瀏覽器窗口的高度減去div的高度爲div的top屬性的值
<!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>
複製代碼
課外知識
  1. document.documentElement.scrollWidth 獲取html元素對象內容的實際寬度,即html元素對象的滾動寬度。
  2. document.documentElement.scrollHeight 獲取html元素對象內容的實際高度,即html元素對象的滾動高度。
  3. document.documentElement.clientLeft 獲取html元素對象的左邊框的寬度。
  4. document.documentElement.clientTop 獲取html元素對象的上邊框的寬度。
  5. document.doucmentElement.offsetLeft 獲取html元素對象相對於整個頁面文檔的位置,也就是html元素的margin。
  6. document.documentElement.offsetTop 獲取html元素對象相對於整個頁面文檔的位置,也就是html元素的margin。
  7. document.documentElement.scrollLeft 設置或獲取頁面文檔向右滾動過的像素數。
  8. document.documentElement.scrollTop 設置或獲取頁面文檔向下滾動過的像素數。

  1. 請實現,鼠標移到頁面中的任意標籤,顯示出這個標籤的基本矩形輪廓。

先前知識
  1. document.body返回當前文檔中的元素或者元素.
  2. nodeType 屬性返回以數字值返回指定節點的節點類型。 若是節點是元素節點,則 nodeType 屬性將返回 1。 若是節點是屬性節點,則 nodeType 屬性將返回 2。 若是節點是文本節點,則 nodeType 屬性將返回 3。
  3. onmouseover 事件會在鼠標指針移動到指定的對象上時發生。
解析
  1. 獲取body中的節點
  2. 若是是元素節點,鼠標移動到上面添加邊框,移出來恢復
  3. 遞歸全部節點
<!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>
複製代碼

  1. js的基礎對象有哪些,window和document的經常使用的方法和屬性列出來

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,
複製代碼

  1. JavaScript中如何對一個對象進行深度clone

解析
  1. 爲空且不爲object類型返回自身
  2. 根據原始值的類型建立一樣類型的值
  3. 遍歷原始值,將原始值中的對象和屬性拷貝到新值,並返回

不反對用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)
複製代碼

  1. js中如何定義class,如何擴展protope?

Ele.className = 「***」; //***在css中定義,形式以下:.*** {…}

A.prototype.B = C;

A是某個構造函數的名字

B是這個構造函數的屬性

C是想要定義的屬性的值
複製代碼

  1. ajax是什麼?ajax的交互模型?同步和異步的區別?如何解決跨域問題?

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標籤
複製代碼

  1. 請給出異步加載js方案,很多於兩種?

默認狀況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的幾種方式


  1. 多瀏覽器檢測經過什麼

Navigator  對象

navigator.appName     保存瀏覽器類型

navigator.appVersion   存有瀏覽器的版本信息

navigator.userAgent     用戶代理
複製代碼

最後,別忘了給這個項目點一個star哦,謝謝支持。

awsome-knowledge-front-end

一個學習編程技術的公衆號。天天推送高質量的優秀博文、開源項目、實用工具、面試技巧、編程學習資源等等。目標是作到我的技術與公衆號一塊兒成長。歡迎你們關注,一塊兒進步,走向全棧大佬的修煉之路

相關文章
相關標籤/搜索