Web前端基础知识整理(一)

339 阅读4分钟

1. typeof返回的数据类型

typeof返回的数据类型包括undefined、string、number、boolean、symbol、Object、Function类型。

2. 检查数组的方式

isArray()方法、toString.call()、instanceof Array

3. js中的call、apply、bind方法的区别

js中的call apply bind都是用来改变方法上下文(context),就是可以使函数可以被其他对象调用。

let hxy = {
    name: 'hxy',
    age: 22,
    say(x, y) {
        console.log(this.name + ':' + this.age + x + y);
    }
}
let yyw = {
    name: 'yyw',
    age: 18
}
hxy.say(1, 2); // 实际上是调用的this.say() this指的是hxy
hxy.say.apply(yyw, [1, 2]);// 调用apply后this改变指向,this指向yyw,相当于yyw.say()
hxy.say.call(yyw, 1, 2);
hxy.say.bind(yyw, 1, 2)(); 

运行结果:

![](https://pic2.zhimg.com/80/v2-18e68719e4f8dd74ab093bcd27164d94_720w.png)

上面的代码就改变了this指向,使得hxy对象的say方法可以被yyw调用

apply与call、bind的区别

apply与call的作用完全相同,只是传参方式不一样,如有下面的函数:

let func = function(arg1, arg2) {

};

就可以通过如下方式来调用:

func.call(this, arg1, arg2);
func.apply(this, [arg1, arg2])
func.bind(this, arg1, arg2)()

call把参数按照顺序传进去,而apply存放在一个数组中

bind()也是用来改变上下文,但是他返回一个方法,不会像call或者apply那样立即调用,

Javascript中存在一种名为伪数组的对象结构。比较特别的是 arguments 对象,还有像调用 getElementsByTagName , document.childNodes 之类的,它们返回NodeList对象都属于伪数组。不能应用 Array下的 push , pop 等方法。

但是我们能通过 Array.prototype.slice.call 转换为真正的数组的带有 length 属性的对象,这样 domNodes 就可以应用 Array 下的所有方法了。

let arguments = Array.prototype.slice.call(arguments);

定义一个 log 方法,让它可以代理 console.log 方法

function log(){
  console.log.apply(console, arguments);
};
log(1);    //1
log(1,2);    //1 2

4.闭包

简单来说,闭包就是指能读取其他函数内部变量的函数
闭包的简单应用:

function f1() {
    var n = 99;
    function f2() {
        return n;
    }
    return f2;
}
var result = f1();
console.log(result());

运行结果返回了f1中的变量n

![](https://pic1.zhimg.com/80/v2-5ec26517d361c381f0bb35cfc075fd5c_720w.png)

闭包的一个作用就是可以读取函数内部的变量,另一个作用就是让闭包中的变量始终保存在内存中,闭包中的变量在函数被调用完后不会被自动清除。(这样也容易引发内存泄漏,因此在用闭包的时候要注意即时清除不需要的变量)

5. js事件机制

DOM事件流分为三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段

事件捕获(event capturing):通俗的理解就是,当鼠标点击或者触发dom事件时,浏览器会从根节点开始由外到内进行事件传播,即点击了子元素,如果父元素通过事件捕获方式注册了对应的事件的话,会先触发父元素绑定的事件。

事件冒泡(dubbed bubbling):与事件捕获恰恰相反,事件冒泡顺序是由内到外进行事件传播,直到根节点。

dom标准事件流的处理顺序为先捕获、再冒泡

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        #parent {
            width: 200px;
            height: 200px;
            text-align: center;
            background: green;
            line-height: 3;
        }

        #child {
            width: 100px;
            height: 100px;
            margin: 0 auto;
            background: orange;
        }
    </style>
</head>

<body>
    <div id="parent">
        父元素
        <div id="child">
            子元素
        </div>
    </div>
    <script type="text/javascript">
        let parent = document.getElementById("parent");
        let child = document.getElementById("child");

        document.body.addEventListener("click", function (e) {
            console.log("click body");
        }, false);

        parent.addEventListener("click", function (e) {
           console.log("click parent");
        }, false);

        child.addEventListener("click", function (e) {
            console.log("click clild");
            //  e.stopPropagation();
        }, false);
    </script>
</body>

</html>

UI界面如下:

![](https://pic4.zhimg.com/80/v2-cce31b66e9525f5e1500693d7e84bada_720w.jpg)

点击子元素会发生什么呢?

![](https://picb.zhimg.com/80/v2-0c404e3706e851ee14cfd7fad6b369b5_720w.png)

点击子元素会发生事件冒泡,先调用子元素的事件,再调用父元素的事件。

addEventListener()的第三个参数为是否采用事件捕获。这里选择false,事件不会进行捕获。

如果想阻止事件冒泡,只需调用e.stopPropagation()即可。在child的回调方法中加入该方法的时候:

可以看到事件没有继续向上传递。

为了测试事件冒泡,我们加入事件冒泡函数:

 parent.addEventListener("click", function (e) {
            console.log("事件捕获");
 }, true);

加入该函数后结果如下:

![](https://pic3.zhimg.com/80/v2-8e172dcf0ccb9cf9b2ea6c73173fcf87_720w.png)

由于先执行事件捕获,因此事件捕获会第一个执行,然后执行事件冒泡。

最后:在学习web前端的过程中,难免会遇到很多的问题,这些问题可能会困扰你许久,为此我有个web开发学习交流群(545667817 ), 里面都是 掘金  的小伙伴,并整理了一份最全面前端学习资料,从最基础的HTML+CSS+JS 到移动端HTML5的项目实战的学习资料都有整理, 想学习的都可以申请加入,大家互相学习,互相交流,共同进步,每日分享不同的学习资料!