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>
//jsconst 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); // undefinedvar 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   结果:undefinedconsole.log("a.prototype:" , a.prototype)//undefinedconsole.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选择器');breakcase '.':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.mzph.cn/news/841102.shtml

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

相关文章

Android窗口管理

一 概述 本篇文章主要讲 Window、WindowManager、WindowManagerService 三者之间的关系及其运行机制。总的来说 Window 表示的是一种抽象的功能集合&#xff0c;具体实现为 PhoneWindow。WindowManager 是外界访问 Window 的入口&#xff0c;对 Window 的访问必须通过 Window…

Socket 函数详细讲解(Socket编程步骤、socket函数、TCP和UDP的区别)

Socket 函数详细讲解和 C 示例 一、 Socket 基本概念1. Socket 简介2. Socket 编程步骤3. TCP Socket 编程示例服务器端客户端 4. 详细说明 二、 socket 函数1. domain 通讯的协议家族2. type 数据传输的类型3. protocol 最终使用的协议返回值示例 三、TCP 和 UDP的区别1. TCP&…

微信小程序预览图片和H5使用canvas实现图片+蒙层+文字

1、效果 2.H5实现 <!--* Author: limingfang* Date: 2024-05-20 10:26:51* LastEditors: limingfang* LastEditTime: 2024-05-21 16:31:11* Description: --> <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8&q…

如何设计小程序的站内信功能

设计小程序的站内信功能&#xff0c;需要考虑用户体验、安全性、功能完整性等方面。以下是设计和实现站内信功能的详细步骤和细节&#xff1a; 目录 1. 需求分析2. 数据库设计用户表&#xff08;Users Table&#xff09;消息表&#xff08;Messages Table&#xff09;用户消息…

C++ | Leetcode C++题解之第112题路径总和

题目&#xff1a; 题解&#xff1a; class Solution { public:bool hasPathSum(TreeNode *root, int sum) {if (root nullptr) {return false;}if (root->left nullptr && root->right nullptr) {return sum root->val;}return hasPathSum(root->left…

Java的类和对象

Java的类和对象 前言一、面向过程和面向对象初步认识C语言Java 二、类和类的实例化基本语法示例注意事项 类的实例化 三、类的成员字段/属性/成员变量注意事项默认值规则字段就地初始化 方法static 关键字修饰属性代码内存解析 修饰方法注意事项静态方法和实例无关, 而是和类相…

变量的命名规则

必须遵守的规则 不能重名不能以数字开头不能使用升序关键字命名不能有特殊符号&#xff08;下划线除外&#xff09; 建议的命名规则&#xff1a;变量名要有含义——>用英文&#xff08;拼音&#xff09;表示变量的作用 非常不建议的命名规则&#xff1a;用汉字命名 常用命…

AI早班车5.25

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是「奇点」&#xff0c;江湖人称 singularity。刚工作几年&#xff0c;想和大家一同进步&#x1f91d;&#x1f91d; 一位上进心十足的【Java ToB端大厂…

题解:CF859C Pie Rules

Luogu - CF859C Analysis 由题意知每个人选择时都是以最佳情况来选&#xff0c;最佳情况是指他的选择能使后面拿的更多。所以决定最佳情况是来自后面。 还有一个重要性质&#xff0c;不管是 Bob 还是 Alice&#xff0c;只要是拥有决策权的人面对同一个局面&#xff0c;其得到…

Bazel编译Android程序

一、编译C程序 1、在项目根目录的WROKSPACE文件添加以下配置 //WORKSPACE文件 load("bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") http_archive(name "rules_android_ndk",sha256 "b1a5ddd784e6ed915c2035c0db536a…

C# 拓展方法(涉及Linq)

拓展方法 定义一个扩展方法使用扩展方法例如再举个例子终极例子 注意事项与Linq 在C#中&#xff0c;扩展方法是一种特殊的静态方法&#xff0c;允许开发者向现有类型“添加”新的方法&#xff0c;而无需修改该类型的源代码或创建新的派生类型。这种机制提供了一种更为灵活的方式…

OpenGL给定直线起点和终点不同的颜色,使用中点Bresenham画线

用鼠标左键按下确定直线起点&#xff0c;鼠标左键抬起确定直线终点。放一部分代码。 // 中点Bresenham算法.cpp : 定义控制台应用程序的入口点。 //#include "stdafx.h" #include <GL/glut.h> #include <iostream> #include <cmath>int windowWidt…

Linux更改系统中的root密码

Linux里面的root密码忘记了怎么办&#xff1f; 1 更改系统中的 root 密码 &#xff08;1&#xff09;键盘 CtrlAltT 快捷键打开终端。 &#xff08;2&#xff09;在终端窗口中输入以下代码&#xff1a; sudo passwd root &#xff08;3&#xff09;输入锁屏密码 &#xf…

解决本地环境正常但Linux服务器上Gson日期解析失败的问题

问题背景 在软件开发过程中&#xff0c;本地环境与服务器环境之间的差异可能导致意外的运行时错误。本文将探讨一个常见的问题&#xff1a;在本地环境中使用 Gson 库解析 JSON 数据时日期字段正常解析&#xff0c;但部署到 Linux 服务器上时却出现 JsonSyntaxException 错误。…

常见的授权场景及其实现方法

在微服务架构中处理授权时&#xff0c;通常考虑多种场景来保证系统的安全性和灵活性。这些场景涵盖了从简单的API权限验证到复杂的基于策略的访问控制。下面&#xff0c;我将详细介绍几种常见的授权场景及其实现方法。 文章目录 1. 简单的权限验证实现方法&#xff1a; 2. 细粒…

从0开始学统计-战斗机保护和代表性抽样

1.什么是抽样研究&#xff1f;为什么要做抽样研究&#xff1f; 抽样研究是一种研究方法&#xff0c;它涉及从整体人群或群体中选取一部分样本来代表整体&#xff0c;以进行研究和推断。在抽样研究中&#xff0c;研究者从总体中选择一个相对较小的样本&#xff0c;通过对这个样…

2024-05学习笔记

最近的学习大多都是和mysql的索引相关的 1.mvcc mvcc是不需要手动配置&#xff0c;是mysql的一个机制 在事务开启时&#xff0c;对涉及到的数据加一个隐藏列&#xff0c;隐藏列对应的值&#xff0c;就是事务id 如果当前是修改操作&#xff0c;就copy一份原来的数据到新的一行…

Topk问题以及二叉树的三种层序遍历和基本操作

一、Topk问题 1、问题描述 TOP-K问题&#xff1a;即求数据结合中前K个最大的元素或者最小的元素&#xff0c;一般情况下数据量都比较大。 比如&#xff1a;专业前10名、世界500强、富豪榜、游戏中前100的活跃玩家等。 2、思路 对于Top-K问题&#xff0c;能想到的最简单直接的…

【npm如何使用以及常用的包npm包的用法】

npm&#xff08;Node Package Manager&#xff09;是Node.js的包管理工具&#xff0c;用于安装、卸载、更新和管理Node.js应用程序的依赖项。以下是npm的基本使用方法和一些常用npm包的用法&#xff1a; 一、npm的基本使用方法 安装npm&#xff1a;npm通常与Node.js一起安装。…

618快到了,送大家一款自动化脚本工具,一起薅羊毛

前言 一年一次的618活动来了&#xff0c;大家做好准备了&#xff0c;奇谈君为大家准备好用的618神器&#xff0c;解放双手&#xff0c;简单操作就可以把红包拿到手。 京淘自动助手 首次使用前需要进行设置 将手机的无障碍权限和悬浮窗权限打开 设置完成后&#xff0c;可以把…