JS闭包、原型链简单理解

目录

1.闭包概念

1.1简单demo1:

1.2简单demo2

1.3使用let代替var解决这个问题

2.函数对象和原型链

​编辑

2.1函数对象demo

2.2.原型链demo

3.使用闭包完成JQuery的一个小demo


1.闭包概念

1.当函数声明时,函数会通过内部属性[scope]来创建范围
2.闭包
 一个函数包着一个函数,闭包是一个函数加上创建函数的作用域的连接,闭包"关闭"了函数的自由变量
    理解:1.2个函数 2个函数作用域[scope]还要连接上;
        2.关闭函数的变量自由,暂时不会销毁(有时会导致内存泄露)
3.无意间共享环境(可以通过闭包解决)

ps:js跟java有一个很大的区别就是,事件函数会延时执行,比如在一个for循环中,里面再执行一个内部方法,java中的内部方法是及时响应并执行完整。但是再js由于事件还未触发会导致,再循环中变量已经被多次执行结束已经被修改,点击的时候需要返回到,在这方法刚被赋予的时候的状态。所以就就需要有一个变量在整个周期中去存储当前执行状态,来保证再次被执行的时候正确。

1.1简单demo1:

问题:

使用闭包解决

特点

function fun(n) {
//此时这个匿名函数就叫做闭包
    return function (m) {
        n += m;
        return n;
    }
}
//会导致内存泄露,一直不回注销
const f = fun(1)
console.log(f(1))

1.2简单demo2

//标签
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>
//js
    const lis = document.getElementsByTagName("li")
    for (var i = 0; i < lis.length; i++) {
        function () {
            lis[i].onclick = function () {
                console.log(i)
            }
        }
//点击li展示为,因为每次输出i的时候找上级
3 3 3

解决方法

    const lis = document.getElementsByTagName("li")
    for (var i = 0; i < lis.length; i++) {
        //function匿名函数就是一个闭包函数
        (function () {
        //使用访问函数记住它运行的环境
            var idx = i;
            lis[i].onclick = function () {
                console.log(idx)
            }
        })()
//输出1,2,3

1.3使用let代替var解决这个问题

因为var的做用户是函数的作用域,所以共享会导致该问题,但入伏哦使用块级就可以解决该问题

    /*
    1.块级作用域,而而不是函数作用域,
        此时let变量的作用域被限制在最近的一次花括号内,不会提升到整个函数作用域
    2.暂时性死区
        console.log(x); // 会报错
        let x = 5;
        //------
        console.log(y); // undefined
        var y = 5;
    3.不允许重复声明
    4.更好的循环,避免常见作用域错误
     */
    for (let i = 0; i < lis.length; i++) {
        lis[i].onclick = function () {
            // alert(i)
            console.log(i)
        }
    }

2.函数对象和原型链

函数也是一种特殊的对象,都是继承object,但是在es6之前,没有引用class这个概念,使用prototype(原型对象)和__proto__(实例对象)来进行关联

在Person.prototype之上是object

2.1函数对象demo

    class A {
        constructor(id) {
            this.id = id
        }
        method1() {
            console.log(this.id)
        }
    }
    A.prototype.bbb=function (){}
    A.prototype.ccc=function (){}
    const a = new A(1);
    a.method1()
    // a.prototype   结果:undefined
    console.log("a.prototype:" , a.prototype)//undefined
    console.log("A.prototype:" , A.prototype)//{ bbb: [Function (anonymous)], ccc: [Function (anonymous)] }
    console.log("a.__proto__:" , a.__proto__)//{ bbb: [Function (anonymous)], ccc: [Function (anonymous)] }
    console.log("a.__proto__.constructor:" , a.__proto__.constructor)//[class A]
    console.log("a.__proto__.constructor.constructor" , a.__proto__.constructor.constructor)//[Function: Function]
    console.log("A.__proto__:" , A.__proto__)//{}

2.2.原型链demo

例子fun.name,当前先找实例对象new -> 原型对象prototype -> 最后object

<script>
    // 原型链 :每一个对象都有一个原型(__proto__),
    //  这个原型还可以拥有自己的原型,形成最终的原型链
    //   查找一个对象特定的属性或方法,
    //   先去:当前对象中找->没有找到则取对象中原型查找->如果没有则去对象的对象中->返回null
    // 函数/类:prototype
    // 对象:_proto_
    //原型链做的是继承
    const Fun = function () {
        //先从当前对象找
        this.name="张三"
    }
    const fun = new Fun()
    Fun.prototype.name="李四"
    // Fun.prototype.prototype.name="王五"
    // Object.prototype.name="王五"
    // console.log(fun.__proto__)
    // console.log(Fun.__proto__)
    // console.log(Fun.prototype)
    console.log(fun.name)
</script>

3.使用闭包完成JQuery的一个小demo

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .box1 {

        }
    </style>
</head>
<body>
<div class="box1"></div>
<div class="box1"></div>
<div></div>
</body>
<script>
    function $(str) {
        //1.先获取对应结点
        function leo(str) {
            this.element = []
            if (str == null) {
                return false;
            }
            const pex = str[0]
            switch (pex) {
                case null:
                    return false;
                case '#':
                    console.log('id选择器');
                    break
                case '.':
                    const elm = str.split('.').at(-1)
                    const elm_doc = document.getElementsByClassName(elm)
                    for (let i = 0; i < elm_doc.length; i++) {
                        this.element.push(elm_doc[i])
                    }
                    break;
                default:
                    console.log("'#' === str.at(0)", '#' === str.at(0))
                    break;
            }
        }

        //2.添加对应事件
        leo.prototype = {
            "css": function (opt) {
                for (let i = 0; i < this.element.length; i++) {
                    for (let j in opt) {
                        this.element[i].style[j] = opt[j]
                    }

                }
                return this;
            },
            "click": function (fn) {
                for (let i = 0; i < this.element.length; i++) {
                    this.element[i].onclick = fn
                }
                return this;
            }
        }
        return new leo(str)
    }

    let i = 0;
    $(".box1").css({
        width: "100px",
        height: "100px",
        background: "#FCF9DF",
        border: "1px solid black "
    }).click(() => {
        alert(i++)
    })
</script>
</html>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值