前端知识点之JavaScript系列1-20 – Python量化投资

前端知识点之JavaScript系列1-20

  1. 目录

    为什么[“1″,”2″,”3”].map(parseInt) 返回[1,NaN,NaN]

开始

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

答案是肯定的,那为什么不是[1,2,3]呢?

知识

首先看看官网上:

paserInt的用法

parseInt() 函数解析一个字符串参数,通过基数解析,返回一个整数或者NAN

parseInt() 的两个参数分别是string和radix

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

注意:

  • 基数不在2-36之间,则返回值就是NAN

map
遍历数组,将数组中的每一个元素调用定义的回调函数,返回包含结果的数组

map()的第一个参数是回调函数,回调函数的三个参数分别是currentValue/index/arr

currentValue是当前值,index当前值的索引,arr当前元素属于的数组对象

解析

那么回到这道题中,[‘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

下面是小编的公众号

一个学习编程技术的公众号。每天推送高质量的优秀博文、开源项目、实用工具、面试技巧、编程学习资源等等。目标是做到个人技术与公众号一起成长。欢迎大家关注,一起进步,走向全栈大佬的修炼之路

https://juejin.im/post/5d7741a6f265da03bd054577

「点点赞赏,手留余香」

    还没有人赞赏,快来当第一个赞赏的人吧!
0 条回复 A 作者 M 管理员
    所有的伟大,都源于一个勇敢的开始!
欢迎您,新朋友,感谢参与互动!欢迎您 {{author}},您在本站有{{commentsCount}}条评论