理论杂记

1、this的指向

  • 关于this的指向是一个比较关键的问题,不论什么时候我们都能遇到

首先:

  • 在全局中

        function foo() {
            var length = 10;
            console.log(this);//window
        }
        var length = 5;
        foo(); // 5
    

    此时的this指向的是全局window

  • 在构造函数中

    function A(name, age) {
        this.name = name;
        this.age = age;
        console.log(this); //  A {name: "张三", age: 18}
    }
    var foo = new A('张三', 18);

此时的this指向的是new出来的实例对象。

  • 在函数被调用时
    var b = {
        AA: function a() {
            console.log(this); //{AA: ƒ}
        }
    }
    b.AA()
    console.log(this); //window

谁调用this,那么this就指向谁。

  • call、apply、bind中的this被强绑定在指定的那个对象上;
    var name = '张三';
    function fun() {
        console.log(this.name);
    }

    var obj = {
        name: '李四'
    };
    fun(); // 张三
    fun.apply(obj); //李四
  • 箭头函数中的this
function Person() {  
    this.age = 0;  
    
    setInterval(() => {
        console.log(this); //Person {age: 3}
        // 回调里面的 `this` 变量就指向了期望的那个对象了
        this.age++;
    }, 3000);
}

var p = new Person();

箭头函数中的this指向的是父级的上下文。

2、事件模型:事件委托、代理?以及让如何让事件先冒泡后排序?

事件模型:

  • 所谓的事件模型就是一种观察者模式的体现,就是当对应的事件被触发时,监听该事件的所有监听函数都会被调用。
    • 观察者模式:又叫订阅者模式,他可以让多个观察者对象同时监听同一个主题对象。当这个主题对象的状态发生变化时同时所有的订阅者,使他们做出反映。

事件代理/委托:

  • 事件在冒泡过程中会上传到父节点,因此可以把子节点的监听函数定义在父节点上,有父节点的监听函数统一处理。
 <div id="box">
        <input type="button" value="按钮" id="btn">
        <input type="button" value="按钮2" id="btn2">
        <input type="button" value="按钮3" id="btn3">
    </div>
    <script>
    var box = document.getElementById('box');
    box.addEventListener('click', function (event) {
        console.log(1);
    });
</script>

事件冒泡:

  • 就是事件自上而下的过程,例如:
<div id="div1">我是div1
        <div id="div2">我是div2
            <div id="div3">我是div3
                <div id="div4">我是div4</div>
            </div>
        </div>
    </div>
        var div1 = document.getElementById("div1");
    var div2 = document.getElementById("div2");
    var div3 = document.getElementById("div3");
    var div4 = document.getElementById("div4");
    div1.addEventListener("click", function () {
        alert("我是div1");

    })

    div2.addEventListener("click", function () {
        alert("我是div2");

    })

    div3.addEventListener("click", function () {
        alert("我是div3");

    })

    div4.addEventListener("click", function () {
        alert("我是div4");

    })
  • 在点击div4的时候,执行顺序是4-3-2-1.

如何让事件先冒泡后排序

    var arr = [2, 3, 4, 5, 2, 34, 21, 12, 21]
    for (var i = 0; i < arr.length - 1; i++) {
        for (var j = 0; j < arr.length - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                var str = arr[j] //当后一项大于前一项
                arr[j] = arr[j + 1]
                arr[j + 1] = str
            }
        }
    }
    console.log(arr);

3、对象和面向对象

什么是对象?

  • 抽象【类】实例化的集合。
    • 拥有属性和方法的一个集合

什么是面向对象?

  • 可以看做是面向事件的结果,是相对于面向过程来说的,面向过程就是实现这一事件结果的具体过程。
  • 面向对象是模型化的,其中包括三大特性:封装、继承、多态。
    • 封装:对于一些公共方法的封装,通过调用来使用这个封装。
    • 继承:从已有的对象下继承出新的对象。
    • 多态:一个变量在引用不同类型的情况下的不同状态。多态开发在开发组件和模块化开发的时候能节省很多资源。

总结:

js本身就是基于面向对象构造出来的(例如:JS中有很多内置类,Array,Object,Function,String;像Promise就是Es6中新增的一个内置类,我们可以基于new Promise来创建一个实例,管理异步编程;

一般我们有的Vue/REACT/JQUWEY 也都是基于面向对象构建出来的,他们都是类,平时开发是都是创建他们的实例来操作的

我们自己真实的项目中,也封过一些组件插件指令(面向对象,插件:Node路由)他们也是基于面向对象开发的,这也可以创造不同的实例,来管理私有属性和公有的方法。

4、for…in和for…of的区别

  • 遍历数组
var arr = [99,88,66,77];
for(let i in arr){
    console.log(i);   //0,1,2,3
}
for(let i of arr){
    consoel.log(i);   //99,88,66,77
}

for...in遍历的是key值。for...of遍历的是vlaue

  • 遍历字符串

同上

  • 遍历对象
    var a = {
        id: 0,
        name: '张三'
    }
    for (let key in a) {
        console.log(key); //id,name
    }
    // for(let key of a){
    //     console.log(key);//: a is not iterable【可迭代对象】
    // }
    for (let key of Object.keys(a)) {
        console.log(key); //id,name
    }

for...in遍历出来的是key值,for…of遍历出来的也是key值,但是要配合Object.keys()来使用,否则报错

5、查找数组重复项

    function res(arr) {
        var temp = [];
        arr.forEach(function (item) {
            if (arr.indexOf(item) !== arr.lastIndexOf(item) && temp.indexOf(item) === -1) {
                temp.push(item)
            }
        })
        return temp;
    }
    var arr = [1, 2, 4, 4, 3, 3, 1, 5, 3];
    console.log(res(arr))
    function res(arr) {
        var temp = [];
        arr.sort().sort(function (a, b) {
            if (a === b && temp.indexOf(a) === -1) {
                temp.push(a)
            }
        })
        return temp;
    }
    var arr = [1, 2, 4, 4, 3, 3, 1, 5, 3];
    console.log(res(arr))

6、数组扁平化

  • 数组扁平化是指将一个多维数组变为一维数组.

1、toString&split

 var arr = [1, [2, 3, [4, 5]]]

    function flatten(arr) {
        return arr.toString().split(',').map(function (item) {
            return Number(item);
        })
    }
    flatten(arr)
    console.log(flatten(arr)); //[1, 2, 3, 4, 5]

2、扩展运算符

    var arr = [1, [2, 3, [4, 5]]]
    function flatten(arr) {
        while (arr.some(item => Array.isArray(item))) {
            arr = [].concat(...arr);
        }
        return arr;
    }
    flatten(arr)
    console.log(flatten(arr)); //[1, 2, 3, 4, 5]

3、递归

function flatten(arr) {
    var res = [];
    arr.map(item => {
        if(Array.isArray(item)) {
            res = res.concat(flatten(item));
        } else {
            res.push(item);
        }
    });
    return res;
}

7、垃圾回收机制

1、什么是垃圾回收机制?

  • 浏览器Javascript具有自动回收机制。

执行环境会负责管理代码在执行过程中使用的内存。

  • 原理

垃圾收集器会定期【周期性】的找出不在使用的变量,然后释放内存。

在执行过程中计算机【gC】会停止响应其他的操作。

  • 注意:

只有函数内部的变量才会被回收。全局变量是不会被回收的。

2、垃圾回收的方式

  • 标记清除

js中最为常用的就是 标记清除,当变量进入环境是,也就是在函数中声明一个变量,就会将这个变量标记为进入环境,在变量离开环境的时候,就会将这个变量标记为 离开环境,从逻辑上讲,是永远不能释放 进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就会用到它们。

  • 引用计数

引用计数的含义就是跟踪记录每个值被应用的次数

  • 当声明一个变量并将一个引用类型赋给这个变量的时候,那么这个值得引用次数就是1,如果同一个值又被赋给了另一个变量,那么这个值得的引用次数加1,
  • 但是当这个包含对这个值的引用变量有取得了另外一个值,那么这个值得引用次数减1,当这个值得引用次数变成0的时候,则说明无法访问这个值了,因而就会将其所占用的内存空间给收了回来。
  • 这样的话,当垃圾回收器下次运行的时候,他就会释放那些引用次数为0的值所占用的内存。

缺点:容易造成内存泄漏。

​ 【在函数执行时,两个对象的属性都被引用,这两个对象的引用次数为2,在函数执行完,两个对象都离开了作用域,但是内存还会存在。】

8、iframe的优缺点有哪些?

使用场景

  • 加载别的网站内容,例如广告
  • 在上传图片时,不用flash实现不刷新
  • 跨域访问的时候可以用到iframe,使用iframe请求不同域名下的资源
  • 典型系统结构,左侧是功能树,右侧是常见的table或者表单一类。为了每一个功能,单独分离出来,采用iframe
  • ajax上传文件

优点:

  • 重载页面时不需要重载整个页面,只需要重新加载页面中的一个框架页(减少数据的传输,减少网页的加载时间)
  • 技术简单,使用方便,主要应用于不需要搜索引擎来搜索的页面。
  • 方便开发,减少代码的重复率,

缺点:

  • 会产生很多的页面,不易于管理。
  • 不易于打印;在控制台查看。
  • 多框架的页面会增加服务器的http请求。
  • 路蓝旗的后退按钮无效。
  • 由于去点太多,HTML5已经不在支持

9、函数柯力化

  • 当一个函数有多个参数的时候,先传递一部分参数(这部分参数以后永不改变)调用它;然后返回一个新的函数接受剩余的参数,返回结果。
  • 创建一个函数,该函数接受一个或者多个function的参数,如果function中所需要的参数都被提供则执行function并返回执行结果,否则,继续返回该函数并等待剩余的参数。
    • 参数就是需要柯力化的函数,
    • 返回值就是柯力化后的函数
    • 目的就是将一个多元函数转换成一个一元函数。
  • 在函数柯力化的时候,在柯力化内部使用闭包,对函数的参数进行缓存,柯力化让函数变得更加的灵活。

10、windowonload事件和domecontentloaded

主要区别:

  • 调用时机不同

  • DocumentContentLoadedDOM树加载完之后立刻触发,

  • DOM树加载完成之后,继续加载图片等外部文件,加载完成之后,onload事件触发。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值