René's URL Explorer Experiment


Title: js没那么简单(3)--内存模型 · Issue #16 · wython/wython.github.io · GitHub

Open Graph Title: js没那么简单(3)--内存模型 · Issue #16 · wython/wython.github.io

X Title: js没那么简单(3)--内存模型 · Issue #16 · wython/wython.github.io

Description: 前言 js的内存模型相对比较简单,可以简单的分为堆内存和栈内存。本节主要讨论,js的内存模型,以及js如何做垃圾回收的。因为垃圾回收,其实对闭包有一定的思考意义。当然,我相信并不是所有人都能认识到这点。 内存模型 内存模型是代码中对硬件运行环境的一个抽象,其可以表示为执行过程中,变量和数据在实时内存中的一个表现。 在历史长河中,语言对内存对分配大体可分为三种,静态分配,堆分配,栈分配。 静态分配 静态分配是最早出现的内存分配模式。我们可以简单理解为,代码需要在最开始时候...

Open Graph Description: 前言 js的内存模型相对比较简单,可以简单的分为堆内存和栈内存。本节主要讨论,js的内存模型,以及js如何做垃圾回收的。因为垃圾回收,其实对闭包有一定的思考意义。当然,我相信并不是所有人都能认识到这点。 内存模型 内存模型是代码中对硬件运行环境的一个抽象,其可以表示为执行过程中,变量和数据在实时内存中的一个表现。 在历史长河中,语言对内存对分配大体可分为三种,静态分配,堆分配,栈分配。 静态...

X Description: 前言 js的内存模型相对比较简单,可以简单的分为堆内存和栈内存。本节主要讨论,js的内存模型,以及js如何做垃圾回收的。因为垃圾回收,其实对闭包有一定的思考意义。当然,我相信并不是所有人都能认识到这点。 内存模型 内存模型是代码中对硬件运行环境的一个抽象,其可以表示为执行过程中,变量和数据在实时内存中的一个表现。 在历史长河中,语言对内存对分配大体可分为三种,静态分配,堆分配,栈分配。 静态...

Opengraph URL: https://github.com/wython/wython.github.io/issues/16

X: @github

direct link

Domain: patch-diff.githubusercontent.com


Hey, it has json ld scripts:
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"js没那么简单(3)--内存模型","articleBody":"### 前言\r\njs的内存模型相对比较简单,可以简单的分为**堆内存**和**栈内存**。本节主要讨论,js的内存模型,以及js如何做垃圾回收的。因为垃圾回收,其实对闭包有一定的思考意义。当然,我相信并不是所有人都能认识到这点。\r\n\r\n### 内存模型\r\n内存模型是代码中对硬件运行环境的一个抽象,其可以表示为执行过程中,变量和数据在实时内存中的一个表现。\r\n\r\n在历史长河中,语言对内存对分配大体可分为三种,**静态分配**,**堆分配**,**栈分配**。\r\n\r\n##### 静态分配\r\n静态分配是最早出现的内存分配模式。我们可以简单理解为,代码需要在最开始时候就确定所使用的内存空间,并且所占用的空间是固定的。这样既不需要内存执行时创建,也不需要摧毁,效率更高。当然,灵活性方面也很差,对于我们现在高级的语言来说。这种方式显得笨拙。\r\n\r\n##### 栈分配\r\n栈分配是后来演变出来的一种比较灵活的内存分配方式。如果你记得前面讲到的动态作用域语言,那么你可以理解到,对于一开始只有栈分配类型的语言,他的作用域是跟着其内存分配走的,意思是:这种类型但分配语言,每次运行时,都是以一种**活动记录**方式压入系统栈。活动记录在你可以看成类似js执行上下文的东西。也就是说,这种分配方式特点是:\r\n1. 程序所涉及到的内存需要提前预知,在运行时固定大小的内存作用类似栈结构的数据结构。\r\n2. 由于其作用域是跟着活动记录存活走,固栈分配的内存摧毁会根据活动记录的销毁而销毁\r\n\r\n##### 堆分配\r\n堆分配相对栈分配则更加灵活,堆分配克服了栈分配内存无法动态分配的缺陷。同时,堆分配使得作用域灵活性更高,比如js的闭包,在栈结构的设计中是无法达成的,但是用堆内存分配之后,闭包具有更灵活的生命周期,而非跟着执行上下文周期去走。\r\n\r\n这种动态内存分配的特性,必然导致了很多其他问题的出现,比如,计算机不能像栈内存那样去确定该内存的存活周期。你可以理解为:堆内存的变量我们无法知道其该在什么时候摧毁。栈内存之所以简单在于其变量是跟着活动记录走。所以堆内存的出现,在c++这种语言中,需要人工分配,人工去释放。这样的意思是:程序对于自己分配的内存具有自己把握的权利,但是对于程序员自己分配的内存,只有程序员知道什么时候可以摧毁。\r\n\r\n后来,类似java这种,借助算法的实现,从而可以固定时间去确定某些变量已经无法继续使用。从而用算法方式去回收它们。这正是我们后面讨论的垃圾回收算法。\r\n\r\n#### js内存模型\r\n在c++中,c++的内存模型会相对更复杂,会有全局静态存储区,堆栈等等。对于js来说,其模型会相对简单很多。可以简单分为**堆内存**和**栈内存**。\r\n\r\n我们可以简单看看这张图片:\r\n![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/1905235e63be49afa5479c97351b8be6~tplv-k3u1fbpfcp-zoom-1.image)\r\n\r\n##### 栈空间(Stack)\r\n在v8中,每一个js进程会有自己管辖的栈空间,内存中的栈空间可以抽象成类似数据结构的后进先出的结构。这样的内存空间,在物理上表现为**连续固定的区域**,在运行时表现为后进先出。比如我们之前提到执行上下文的概念,可以认为是对整个块环境的一个完整处理,那执行上下文中的数据以栈分配形式存储。\r\n\r\n而在实际v8的运行过程中,栈空间的处理是类似于游标的指针决定。类似于下图的游标,很多时候我们对内存对处理不会像现实中那样,真正意义上对清理,游标下移,表示游标以上对空内存为空闲,这时候可以认为其已经出栈。在程序中,我们可以在用到时候覆盖这块内存,所以不需要显式处理\r\n![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/2e675fc07ec44ffe8c92648ea8c3ca94~tplv-k3u1fbpfcp-zoom-1.image)\r\n\r\n##### 堆空间(Heap)\r\n在v8中,对堆空间堆划分会比较详细很多,这也难怪,堆是具有灵活多变堆一种内存分配方式。在物理上表现为**不一定连续不固定大小区域**,在运行时,它可以根据代码上需要的空间,动态分配需要的内存。同时,最大的特点和问题,也是我们经常关注的内存回收问题。我们知道,在c++中,部分人为堆内存的分配是由人自己去释放。这是因为堆的灵活性,导致其回收也具有一定灵活性,无法像栈结构那样有确定的生命周期。\r\n\r\n而在js中,语言的灵活性更高。好在js有灵活的算法去确定其是否需要回收,并且定时进行回收。\r\n![](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/dd73556a0e4f4fdf86a447a51cb87e10~tplv-k3u1fbpfcp-zoom-1.image)\r\n\r\n按v8的堆内存做划分:\r\n- **新生代(new space)**:新生代和老生代是我们的js代码所能分配的空间,是垃圾回收主要关注的区域,新生代主要存生命周期比较短的变量和内容。所以空间较小,但是变更频繁。\r\n- **老生代(old space)**:老生代是生命周期较长的分配区域,空间大,不过相对变化比较不频繁。新生代和老生代在后面垃圾回收会主要讲解,他们垃圾回收关注的主要区域。\r\n- **大对象空间(Large object space)**:超过内存限制的大对象会在这里开辟空间。\r\n- **代码空间(Code-space)**:在我们前面提到,执行上下文中,会有些编译后的二进制可执行代码,函数的过程代码,大部分会存储在这个区域。有一部分也会存储在大对象空间。\r\n- **细胞空间,属性细胞空间,map 空间(Cell space, property cell space, and map space)**:这些空间分别包含:Cells, PropertyCells, 和 Maps的数据结构。这个空间的大小结构是固定的。\r\n\r\n#### js数据类型和内存模型的关系\r\n\r\n通过上面的讨论,我们对内存对模型有个基本的认识。但是所有的知识,不能脱离js本身。那么在js中,我们对数据对使用,在内存中又是如何具体体现对呢?\r\n\r\n首先,我们得知道js的数据类型有哪些,在js中,有八种基本的数据类型:\r\n\r\n1. **Boolean**: true或者false\r\n2. **Number**: 数字类型,固定64位空间。\r\n3. **String**: 字符串类型\r\n4. **Undifined**:一个没有值的空间,默认会是undifined。前面提到的变量提升之后,由于变量没有具体执行的内容,表现即为undifined。\r\n5. **Null**: 就是null\r\n6. **Symbol**: es6中新引入的一种类型\r\n7. **BigInt**: 具有大空间的整型\r\n8. **Object**: 引用类型基类,我们称它对象,函数,数组等特殊结构都是以它实现的。\r\n\r\n在这八种类型中,Object我们叫**引用类型**,其他七种叫**基本数据类型**。这么区分的原因在于他们在内存分配上的区别导致的。\r\n\r\n我们先简单的说,基本类型是存储在栈结构中,而引用类型存储在堆结构中。为什么要这么去划分,这是一个值得思考的问题。\r\n这是因为,基本结构具有可提前预知,固定的数据大小,所以可以满足用栈存储的前提条件。而引用类型,他们的大小是会动态变化的,我们知道,堆的优点就是动态分配,所以引用类型需要借助堆动态分配的方式,灵活的变化空间。\r\n\r\n这里我们用具体代码来看看:\r\n\r\n```javascript\r\nvar a = 100\r\na = a + 100\r\n\r\nvar b = []\r\nb.push(1)\r\n```\r\n\r\n上面代码中,我们知道,对于number类型来说,64位固定大小空间,无论是100,还是200,都是用64位表示。所以当我们如果数字较大,就会溢出。这其实是固定位数大小的体现。而对于array类型来说,其存储的空间会不断真正意义上的变化。比如十个长度的数组和20个长度的数组其占用空间就不一样。\r\n\r\n如此,array只能用堆动态分配才能满足其要求。\r\n\r\n接下来,我们在看看两种不同类型如何用体现:\r\n![](https://p9-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/aed3c51ea18943b7a6fe15bb28c7b100~tplv-k3u1fbpfcp-zoom-1.image)\r\n\r\n对于栈空间,变量a是基本数据类型,所以具有唯一内存标识,对应在栈里面的一个值。而对于变量b,执行上下文也会为其分配一定的栈内存,不过存储的是指向堆的一个内存区域,用于数组的存储,该数组是动态分配的。这样很好的看出,基本类型和引用类型在存储上的区别了。\r\n\r\n#### 包装类型\r\n看过高级程序设计的书的同学应该知道,基本类型具有如引用类型一样特殊的方法,比如toString方法。相信大部分人,不会去过多思考这个东西,也许你们只是简单了解到它的特性,比如包装的周期很短,仅仅在于用到的语句间存活。但是其实包装类型体现了更多有趣的东西,正好验证了我们上面的说法。\r\n\r\n这里先回顾下包装类型的特点\r\n\r\n我们知道,基本类型都具有自己的构造函数,这个构造函数的原型是Object。所以他们的实例具有Object的方法,也具有一些自身的特殊方法。\r\n\r\n但是我们前面又说到,基本类型是存储在栈内存,它的大小是固定的,它不应该有类型Object这种面向对象方式的灵活方法。这似乎是矛盾的,一方面它表现像实例,一方面它又是固定结构。\r\n\r\n只有在这个层面上思考,你才真正能理解到包装类型的本质,包装类型的意思,真是如它名字表示的,包装。也就是说,在运行的时候,如果基本类型用了如对象一样的函数调用,那么会把基本类型做一个包装,让他表现的像一个对象。而与我们自己使用的对象类型不同,由于这个包装是编译器自己产生的,所以编译器会在其使用完之后,立即摧毁掉对应的对象。\r\n\r\n**如何理解这个行为,我们知道,垃圾回收是比较复杂的,对于这种编译器自己具有控制权,并且知道生命周期的堆内存空间,这种用完立即摧毁的方式是理所当然的。**\r\n\r\n我们可以用代码简单的去抽象这个行为:\r\n\r\n```javascript\r\nvar a = 1\r\n\r\nconsole.log(a.toString())\r\n\r\na = a + 1\r\n\r\n// 以上代码会转化称\r\n\r\nvar a = 1\r\n\r\nvar tem = a     // 包装\r\na = new Number(tem) // 包装\r\nconsole.log(a.toString())  // 包装\r\na = tem         // 包装\r\n\r\na = a + 1\r\n```\r\n\r\n正如上面代码,a在用到toString的时候会进行包装,但是用完也会立即回收Number类型的包装。这样有利于更好利用堆空间。这里希望你在细细体会。\r\n\r\n另外,在ts中,会对包装类型和基本类型做区别,体现为number和Number的类型。\r\n\r\n最后,由于篇幅的原因,垃圾回收就放后面讲了,这里就先提出一个内存模型概念就好了。end\r\n\r\n相关题目:\r\n1. 1 为什么没有toString方法\r\n2. 1 为什么能调用toString方法\r\n3. 1 和 new Number(1)在内存占用上有什么区别\r\n4. Number(1) 和 new Number(1) 的区别\r\n5. ts中Number和number类型有什么区别","author":{"url":"https://github.com/wython","@type":"Person","name":"wython"},"datePublished":"2020-08-20T02:30:29.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/16/wython.github.io/issues/16"}

route-pattern/_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format)
route-controllervoltron_issues_fragments
route-actionissue_layout
fetch-noncev2:58d9ba20-79cf-8db1-bc2a-58a504c0718a
current-catalog-service-hash81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114
request-idA98A:1BDD2D:1554437:1B38F31:69756277
html-safe-nonce076dff3133882543180b2486731b1d5ec66f897694a3a20c3c296443473b745c
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBOThBOjFCREQyRDoxNTU0NDM3OjFCMzhGMzE6Njk3NTYyNzciLCJ2aXNpdG9yX2lkIjoiNDkwMDk0ODIwMjExMTcyMjEwNCIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9
visitor-hmac8839222b7a6df43b91389d7f225a192913135beae968c1e75f9bd0f2abc86d62
hovercard-subject-tagissue:682317873
github-keyboard-shortcutsrepository,issues,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///voltron/issues_fragments/issue_layout
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/wython/wython.github.io/16/issue_layout
twitter:imagehttps://opengraph.githubassets.com/05feb806f27dc1d15766186b67197aaf394071d55a6096553001d921b24d57e4/wython/wython.github.io/issues/16
twitter:cardsummary_large_image
og:imagehttps://opengraph.githubassets.com/05feb806f27dc1d15766186b67197aaf394071d55a6096553001d921b24d57e4/wython/wython.github.io/issues/16
og:image:alt前言 js的内存模型相对比较简单,可以简单的分为堆内存和栈内存。本节主要讨论,js的内存模型,以及js如何做垃圾回收的。因为垃圾回收,其实对闭包有一定的思考意义。当然,我相信并不是所有人都能认识到这点。 内存模型 内存模型是代码中对硬件运行环境的一个抽象,其可以表示为执行过程中,变量和数据在实时内存中的一个表现。 在历史长河中,语言对内存对分配大体可分为三种,静态分配,堆分配,栈分配。 静态...
og:image:width1200
og:image:height600
og:site_nameGitHub
og:typeobject
og:author:usernamewython
hostnamegithub.com
expected-hostnamegithub.com
None4a4bf5f4e28041a9d2e5c107d7d20b78b4294ba261cab243b28167c16a623a1f
turbo-cache-controlno-preview
go-importgithub.com/wython/wython.github.io git https://github.com/wython/wython.github.io.git
octolytics-dimension-user_id15258919
octolytics-dimension-user_loginwython
octolytics-dimension-repository_id142893945
octolytics-dimension-repository_nwowython/wython.github.io
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id142893945
octolytics-dimension-repository_network_root_nwowython/wython.github.io
turbo-body-classeslogged-out env-production page-responsive
disable-turbofalse
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
release488b30e96dfd057fbbe44c6665ccbc030b729dde
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://patch-diff.githubusercontent.com/wython/wython.github.io/issues/16#start-of-content
https://patch-diff.githubusercontent.com/
Sign in https://patch-diff.githubusercontent.com/login?return_to=https%3A%2F%2Fgithub.com%2Fwython%2Fwython.github.io%2Fissues%2F16
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub SparkBuild and deploy intelligent appshttps://github.com/features/spark
GitHub ModelsManage and compare promptshttps://github.com/features/models
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
GitHub SponsorsFund open source developershttps://github.com/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/accelerator
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://patch-diff.githubusercontent.com/login?return_to=https%3A%2F%2Fgithub.com%2Fwython%2Fwython.github.io%2Fissues%2F16
Sign up https://patch-diff.githubusercontent.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fvoltron%2Fissues_fragments%2Fissue_layout&source=header-repo&source_repo=wython%2Fwython.github.io
Reloadhttps://patch-diff.githubusercontent.com/wython/wython.github.io/issues/16
Reloadhttps://patch-diff.githubusercontent.com/wython/wython.github.io/issues/16
Reloadhttps://patch-diff.githubusercontent.com/wython/wython.github.io/issues/16
wython https://patch-diff.githubusercontent.com/wython
wython.github.iohttps://patch-diff.githubusercontent.com/wython/wython.github.io
Notifications https://patch-diff.githubusercontent.com/login?return_to=%2Fwython%2Fwython.github.io
Fork 0 https://patch-diff.githubusercontent.com/login?return_to=%2Fwython%2Fwython.github.io
Star 10 https://patch-diff.githubusercontent.com/login?return_to=%2Fwython%2Fwython.github.io
Code https://patch-diff.githubusercontent.com/wython/wython.github.io
Issues 14 https://patch-diff.githubusercontent.com/wython/wython.github.io/issues
Pull requests 0 https://patch-diff.githubusercontent.com/wython/wython.github.io/pulls
Actions https://patch-diff.githubusercontent.com/wython/wython.github.io/actions
Projects 0 https://patch-diff.githubusercontent.com/wython/wython.github.io/projects
Security 0 https://patch-diff.githubusercontent.com/wython/wython.github.io/security
Insights https://patch-diff.githubusercontent.com/wython/wython.github.io/pulse
Code https://patch-diff.githubusercontent.com/wython/wython.github.io
Issues https://patch-diff.githubusercontent.com/wython/wython.github.io/issues
Pull requests https://patch-diff.githubusercontent.com/wython/wython.github.io/pulls
Actions https://patch-diff.githubusercontent.com/wython/wython.github.io/actions
Projects https://patch-diff.githubusercontent.com/wython/wython.github.io/projects
Security https://patch-diff.githubusercontent.com/wython/wython.github.io/security
Insights https://patch-diff.githubusercontent.com/wython/wython.github.io/pulse
New issuehttps://patch-diff.githubusercontent.com/login?return_to=https://github.com/wython/wython.github.io/issues/16
New issuehttps://patch-diff.githubusercontent.com/login?return_to=https://github.com/wython/wython.github.io/issues/16
js没那么简单(3)--内存模型https://patch-diff.githubusercontent.com/wython/wython.github.io/issues/16#top
https://github.com/wython
https://github.com/wython
wythonhttps://github.com/wython
on Aug 20, 2020https://github.com/wython/wython.github.io/issues/16#issue-682317873
https://camo.githubusercontent.com/04f741913c232f5119d7919f382e6d9f175f6cc389219220b761bdfa202548ff/68747470733a2f2f70312d6a75656a696e2e62797465696d672e636f6d2f746f732d636e2d692d6b3375316662706663702f31393035323335653633626534396166613534373963393733353162386265367e74706c762d6b3375316662706663702d7a6f6f6d2d312e696d616765
https://camo.githubusercontent.com/ce195e23ddd306ba917c46c374a718332808dd6ea88b4c6fbe7c56db4461e488/68747470733a2f2f70312d6a75656a696e2e62797465696d672e636f6d2f746f732d636e2d692d6b3375316662706663702f32653637356663303765633434666665386339323634386561386333636139347e74706c762d6b3375316662706663702d7a6f6f6d2d312e696d616765
https://camo.githubusercontent.com/27094e750d806d320f421dc6e38b2057597728cb4e44db69fe3e8c7ebb3ebe0d/68747470733a2f2f70312d6a75656a696e2e62797465696d672e636f6d2f746f732d636e2d692d6b3375316662706663702f64643733353536613065346634666466383661343437613531636238376531307e74706c762d6b3375316662706663702d7a6f6f6d2d312e696d616765
https://camo.githubusercontent.com/cd7277d24e949192c51c48ea641cd14e72a24e95decf06baf3bd11b5a60a6d8a/68747470733a2f2f70392d6a75656a696e2e62797465696d672e636f6d2f746f732d636e2d692d6b3375316662706663702f61656433633531656131383934336237613666653135626232386337623130307e74706c762d6b3375316662706663702d7a6f6f6d2d312e696d616765
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.