JS闭包、原型链简单理解

news2024/12/23 23:07:59

目录

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>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1695912.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

出书,是「盖你自己的房子」你知道吗?

出书是「盖你自己的房子」 尊敬的出书盟友&#xff1a; 你好&#xff01;我希望这封信能够激发您对出书和阅读的热情。 在当今信息爆炸的时代&#xff0c;每个人都有机会分享自己的故事、思想和知识。而书籍作为一种流传百年的媒体&#xff0c;依旧承载着无限的力量和影响力…

HE TB PPDU MU-RTS

看起来像是MU-RTS的触发帧的应答不是HE TB PPDU&#xff0c;而是传统得的帧&#xff0c;应答CTS。 非AP 的STA&#xff0c;是不能发送触发帧&#xff0c;也就是说&#xff0c;触发帧&#xff0c;只能是由AP发送给STA

【CCF-CSP】 202309-3 梯度求解

思路&#xff1a; 将表达式整理成只有目标求导变量的无括号加法表达式&#xff0c;其他变量均代入其值&#xff0c;然后利用最简单的求导公式&#xff0c;求出最终值。 样例1 x1 x1 x1 * x2 *转换成 x1*x1*x1x1*x2 若求导x1&#xff0c;则只留下x1&#xff0c;变为 x1*x1*x1…

python:__set_name__使用

python&#xff1a;__set_name__使用 1 前言 在Python中&#xff0c;我们可以通过__set_name__方法来实现一些特殊的操作。该方法是在定义类的时候被调用&#xff0c;用于设置属性的名称。这样一来&#xff0c;我们就可以在类定义中动态地获取属性的名称&#xff0c;从而更好…

转行一年了

关注、星标公众号&#xff0c;直达精彩内容 ID&#xff1a;技术让梦想更伟大 整理&#xff1a;李肖遥 来公司一年了。 说是转行其实还是在半导体行业&#xff0c;熟悉我的朋友知道 &#xff0c;我在18年开始进入半导体行业&#xff0c;那个时候想着行业很重要&#xff0c;站对了…

LearnOpenGL(二十)之立方体贴图

一、创建立方体贴图 首先&#xff0c;生成一个纹理&#xff0c;并将其绑定到纹理目标GL_TEXTURE_CUBE_MAP&#xff1a; unsigned int textureID; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_CUBE_MAP, textureID); 因为立方体贴图包含有6个纹理&#xff0…

Go微服务: Http服务注册在Consul的示例(非Go-Micro)

概述 现在&#xff0c;我们使用consul客户端的api来把Http服务注册到consul上&#xff0c;非Go-Micro的形式其实&#xff0c;consul官方提供了对应的接口调用来实现&#xff0c;golang中的consul/api包对其进行了封装我们使用consul/api来进行展示 目录结构 gitee.com/go-mi…

Day39贪心算法part06

LC738单调递增的数字&#xff08;未掌握&#xff09; 思路分析&#xff1a;一旦出现strNum[i - 1] > strNum[i]的情况&#xff08;非单调递增&#xff09;&#xff0c;首先想让strNum[i - 1]–&#xff0c;然后strNum[i]给为9字符串是不可变的&#xff0c;不可以使用s.char…

图像处理案例01

案例01 例011.1 目标1.2 步骤1.3 代码 例01 1.1 目标 找出图形中的圆弧。 1.2 步骤 读入图像。彩色图转灰度图。图像处理。读灰度图阈值分割&#xff0c;得到img_thre&#xff0c;除掉图中的蓝色和绿色&#xff0c;只留下白色。对img_thre做水平梯度得到gx&#xff0c;这样…

ESP32-C3模组上跑通OTA升级(9)

接前一篇文章&#xff1a;ESP32-C3模组上跑通OTA升级&#xff08;8&#xff09; 本文内容参考&#xff1a; 《ESP32-C3 物联网工程开发实战》 乐鑫科技 特此致谢&#xff01; 七、固件版本 将不同功能的固件标记为不同版本是方便后期维护的一个重要手段。ESP-IDF提供了一些标…

飞机大战游戏实现揭秘

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、游戏概览与核心玩法 二、游戏模块详解 1. 游戏主循环模块 2. 创建初始化模块 三、关…

LeetCode:74.搜索二维矩阵

class Solution(object):def searchMatrix(self, matrix, target):M, N len(matrix), len(matrix[0])for i in range(M):for j in range(N):if matrix[i][j] target:return Truereturn False代码解释 这段代码定义了一个名为 Solution 的类&#xff0c;其中包含一个方法 sea…

华为OD机试【找出通过车辆最多颜色】(java)(100分)

1、题目描述 在一个狭小的路口&#xff0c;每秒只能通过一辆车&#xff0c;假设车辆的颜色只有 3 种&#xff0c;找出 N 秒内经过的最多颜色的车辆数量。 三种颜色编号为0 &#xff0c;1 &#xff0c;2。 2、输入描述 第一行输入的是通过的车辆颜色信息[0,1,1,2] &#xff0…

【gradle】MAC下用gradle构建部署springboot项目

MAC下用gradle构建部署springboot项目 前言下载安装配置gradle下载安装下载可能出现的问题 &#xff08;zsh: command not found: brew&#xff09; 配置环境变量配置国内下载源全局配置单个项目配置 通过idea构建项目构建后的项目结构 小结延伸 前言 好久以前就听说gradle了&…

CentOS 7安装alertmanager

说明&#xff1a;本文介绍如何在CentOS 7安装alertmanager&#xff1b; Step1&#xff1a;下载安装包 访问Github仓库&#xff0c;下载对应版本的alertmanager安装包 https://github.com/prometheus/alertmanager/releases 如何查看自己系统的信息&#xff0c;可参考下图中的…

求斐波那契数列第n项的值

本期介绍&#x1f356; 主要介绍&#xff1a;什么是斐波那契数列&#xff0c;递归实现求斐波那契数列第n项值&#xff0c;递归法为什么不适合求斐波那契数&#xff0c;用迭代法实现求斐波那契数列的值&#x1f440;。 文章目录 1. 斐波那契数列是什么&#xff1f;2. 题目2. 递归…

HTML+CSS 玻璃按钮

效果演示 Code <!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>玻璃按钮</title><li…

游戏子弹类python设计与实现详解

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、引言 二、子弹类设计思路 1. 属性定义 2. 方法设计 三、子弹类实现详解 1. 定义子弹…

ubuntu openvoice部署过程记录,解决python3 -m unidic download 时 unidic无法下载的问题

github给的安装顺序&#xff1a; conda create -n openvoice python3.9 conda activate openvoice git clone gitgithub.com:myshell-ai/OpenVoice.git cd OpenVoice pip install -e .安装MeloTTS: pip install githttps://github.com/myshell-ai/MeloTTS.git python -m unid…

从0开始学统计-方差分析

1.什么是方差分析&#xff1f; 方差分析&#xff08;ANOVA&#xff0c;Analysis of Variance&#xff09;是一种统计方法&#xff0c;用于比较三个或三个以上组之间的平均值是否存在显著差异。它适用于以下情况&#xff1a; &#xff08;1&#xff09; 当我们有三个或三个以上…