JavaScript看这一篇就够了,简单全面一发入魂-程序员宅基地

技术标签: JavaScript与Vue基础教程系列  javascript  

一、什么是JavaScript

1、DOM

文档对象模型(DOM,Document Object Model)是一个应用编程接口(API),用于在HTML中使用扩展的HTML。DOM将整个页面抽象为一组分层节点。
DOM通过创建表示文档的树,让开发者可以随心所欲的控制网页的内容和结构。使用DOM API可以轻松地删除、添加、替换、修改节点。
对浏览器而言,DOM就是使用ECMAScript实现的,如今已经成为JavaScript语言的一大组成部分。
言而言之,DOM提供与网页内容交互的方法和接口。

2、BOM

IE3和Netscape Navigator3提供了浏览器对象模型(BOM)API,用于支持访问和操作浏览器的窗口。使用BOM,开发者可以操控浏览器显示页面之外的部分。
BOM的能力展示:

  1. 弹出新浏览器窗口的能力;
  2. 移动、缩放和关闭浏览器窗口的能力;
  3. navigator对象,提供关于浏览器的详尽信息;
  4. location对象,提供浏览器加载页面的详尽信息;
  5. screen对象,提供关于用户屏幕分辨率的详尽信息;
  6. performance对象,提供浏览器内存占用、导航行为和时间统计的详尽信息;
  7. 对cookie的支持;
  8. 其它自定义对象,如XMLHttpRequest和IE的ActiveXObject。
    简而言之,BOM提供与浏览器交互的方法和接口。

二、HTML中的JavaScript

1、script标签

<script>标签有8大属性,可以包含来自外部域的JavaScript文件,<script>的src属性可以是一个完整的URL,并且这个URL指向的资源可以跟包含它的HTML页面不在同一个域中,浏览器解析这个资源时,会想src属性指定的路径发送一个GET请求,以取得相应资源,这个初始的请求不受浏览器同源策略限制,但返回并被执行的JavaScript则受限制。当然,这个请求仍然受父页面HTTP/HTTPS协议的限制。

2、标签位置

过去,所有的<script>标签都放在head标签中,这就意味着所有JavaScript代码都要下载、解析和解释完成后,才能开始渲染页面(页面在浏览器解析到<body>标签的起始标签时开始渲染)。对于需要很多JavaScript的页面,会导致页面渲染的明显延迟,在此期间浏览器窗口完全空白。
为了解决这个问题,现代Web应用程序通常将所有JavaScript引用放在<body>元素中的页面内容后面。

3、延迟执行脚本

正常情况下,JavaScript的代码是书序执行的。
defer脚本会延迟到整个页面都解析完毕后再运行,只适用于外部脚步。
async脚本与defer脚本类似,都是只适用于外部脚本,但async脚本并不能保证按照它们出现的次序执行。

4、动态加载脚本

JavaScript可以通过向DOM中动态添加script元素同样可以加载指定的脚本,只要创建一个script元素并将其添加到DOM即可。

let script = document.createElement('script');
script.src = 'nezha.js';
document.head.appendChild(script);

默认情况下,以这种方式创建的<script>标签都以异步方式加载,相当于加了async标签。

5、将JavaScript代码独立于HTML的好处

  1. 可维护性
  2. 缓存。浏览器会根据特定的设置缓存所有外部链接的JavaScript文件,这意味着如果两个页面都用到同一个JavaScript文件,则该文件只需加载一次,这最终意味着页面加载更快。

三、语言基础

1、严格区分大小写

2、ECMAScript中的语句推荐以分号结尾

  1. 加分号有助于防止省略造成的问题
  2. 避免输入内容不完整
  3. 便于开发者通过删除空行来压缩代码(如果没有结尾的分号,只删除空行,则会导致语法错误)
  4. 加分号有助于提升性性能,因为解析器会尝试在合适的位置补上分号以纠正语法错误。

四、对比var与let、const

  1. let不具备声明提升,var具备声明提升
  2. let声明的范围是块作用域,而var声明的范围是函数作用域。
  3. let是ES6才引入的声明关键字
  4. for循环中的let声明
  5. const与let很相似,最大的区别是const必须初始化,且不能再次赋值。

结语:

  1. 不使用var,有了let和const,大多数开发者会发现自己不再需要var了,限制自己只使用let和const,有助于提升代码质量,因为变量有了明确的作用域、声明位置、以及不变的值。
  2. const优先,let次之。使用const声明可以让浏览器运行时强制保持变量不变,也可以让静态代码分析工具提前发现不合法的赋值操作。

五、对象池管理

通过创建对象池管理一组可回收的对象,应用程序可以向这个对象池请求一个对象、设置其属性,使用他,然后
在操作完成后再把它交还给对象池,因为没有对象初始化,垃圾回收探测刽发现兑现更替,因此垃圾回收程序就不会频繁调用了。

let v1 = vectorPool.allocate();
let v2 = vectorPool.allocate();
let v3 = vectorPool.allocate();

v1.x = 10;
v1.y = 5;
v2.x = 11;
v2.y = 12;

addVector(v1,v2,v3);

vectorPool.free(v1);
vectorPool.free(v2);
vectorPool.free(v3);

由于数组是动态可变的,当创建一个大小为100的数组,使用时发现不够大,引擎会删除这个数组,然后创建一个新的,
垃圾回收程序会看到这个删除操作,然后很快的就来收一次垃圾,要避免这种动态分配操作。

六、变量、作用域、内存

JavaScript变量可以保存两种类型的值:原始值和引用值。

1、原始值6种数据类型

  1. Undefined
  2. Null
  3. Boolean
  4. Number
  5. String
  6. Symbol

2、原始值和引用值特点

  1. 原始值大小固定,保存在栈内存中
  2. 从一个变量到另一个变量复制原始值,会创建该值得第二个副本
  3. 引用值是对象,存储在堆内存中
  4. 包含引用值的变量实际上只包含指向相应对象的一个指针,而不是对象本身
  5. 从一个变量到另一个变量复制引用值,只会复制指针,因此结果是两个变量都指向同一个对象
  6. typeof操作费可以确定值的原始类型,instanceof操作符用于确保值得引用类型

3、执行上下文

任何变量都存在于某个执行上下文中(也称为作用域)。这个上下文(作用域)决定了变量的生命周期,以及它们可以访问代码的哪些部分。
执行上下文可以总结如下:

  1. 执行上下文分为 ① 全局上下文、② 函数上下文、③ 块级上下文
  2. 代码执行流每进入一个新上下文,都会创建一个作用域链,用于搜索变量和函数
  3. 函数或块的局部上下文不仅可以访问自己作用域内的变量,也可以访问任何包含上下文乃至全局上下文的变量
  4. 全局上下文只能访问全局上下文中的变量和函数,不能直接访问局部上下文中的任何数据
  5. 变量的执行上下文用于确定什么时候释放内存

4、JavaScript垃圾回收

JavaScript是使用垃圾回收的编程语言,开发者不需要操心内存分配和回收。

  1. 离开作用域的值会被自动标记为可回收,然后在垃圾回收期间被删除
  2. 主流的垃圾回收算法是标记算法,即先给当前不使用的值加上标记,再回来回收它们的内存
  3. 引用计数是另一种垃圾回收策略,需要记录值被引用了多少次。JavaScript引擎不再使用这种算法,但某些旧版本的IE仍然会受这种算法的影响,原因是JavaScript会访问非原生JavaScript对象(如DOM对象)。
  4. 引用计数在代码中循环引用时会出现问题
  5. 解除变量的引用不仅可以消除循环引用,而且对垃圾回收也有帮助。为促进内存回收,全局对象、全局对象的属性和循环引用都应该在不需要时解除引用。

七、map基础API

1、set()方法添加键值对

2、get()和has()进行查询

3、delete()和clear()进行删除

4、size获取map获取键值对数量

八、顺序与迭代

与Object的主要差异是,map实例会维护键值对的插入顺序,可以根据插入顺序执行迭代操作。
映射实例可以通过迭代器Iterator,能以插入顺序生成[key,value]形式的数组,可以通过entries()方法,或者Symbol.iterator属性,它引用entries()取得这个迭代器。

const map = new Map([
	["id","1"],
	["name","哪吒"],
	["age","18"]
]);

for(let x of map.entries()){
    
	alert(x);
}
//[id,1]
//[name,哪吒]
//[age,18]

for(let x of map[Symbol.iterator]()){
    
	alert(x);
}
//[id,1]
//[name,哪吒]
//[age,18]

map.foreach((val,key) => alert(`${
      key} -> ${
      val}`));
//id -> 1
//name -> 哪吒
//age -> 18

for(let key of map.keys()){
    

}

for(let v of map.values()){
    

}

九、Object和Map到底有什么区别?

1、内存占用

给定固定大小内存的情况下,Map一般会比Object多存储50%的键值对。

2、插入性能

插入Map一般会稍微快一点。

3、查找速度

相差无几。

4、删除性能

Map的删除性能完胜Object。
综上四点,选择Map显然是更好地选择。

十、Set

1、基础API

  1. 添加add()
  2. 查询has()
  3. 获取数量size
  4. 删除delete()
  5. 清空clear()

2、顺序与迭代

Set会维护值插入时的顺序,因此支持按顺序迭代。
集合实例可以提供一个迭代器Iterator,能以插入顺序生成集合内容。可以通过values()方法及其别名方法keys(),或者Symbol.iterator属性,他引用values(),取得这个迭代器。

const s = new Set("哪吒","云韵","比比东");

alert(s.keys === s[Symbol.iterator]);//true
alert(s.values === s[Symbol.iterator]);//true

for(let value of s.values()){
    

}

for(let value of s[Symbol.iterator]){
    

}

因为values()是默认迭代器,所以可以直接对集合实例使用扩展操作,把集合转为数组:

const s = new Set("哪吒","云韵","比比东");
console.log([...s]);//["哪吒","云韵","比比东"]

十一、什么是生成器

1、生成器简介

生成器是ECMAScript6新增的一个极为灵活的结构,拥有在一个函数块内暂停和恢复代码执行的能力。这种新能力具有较深远的影响,比如,使用生成器可以自定义迭代器和实现协程。
生成器的形式是一个函数,函数名称前面加一个星号*,表示它是一个生成器。只要是可以定义函数的地方,就可以定义生成器。
调用生成器函数会产生一个生成器对象,生成器对象一开始处于暂停执行(suspended)状态。与迭代器相似,生成器对象也实现了Iterator接口,因此具有next()方法。调用这个方法会让生成器开始或恢复执行。
next()方法的返回值类似于迭代器,有一个done属性和一个value属性。函数体为空的生成器函数中间不会停留,调用一次next()就会让生成器到达done:true状态。
value属性是生成器函数的返回值,默认值为undefined,可以通过生成器函数的返回值指定:

function * generatorFn(){
    
	return '哪吒编程'
}

生成器函数只会在初次调用next()方法之后开始执行。

2、通过yield中断执行

yield关键字可以让生成器停止和开始执行,也是生成器最有用的地方,生成器函数在遇到yield关键字之前会正常执行。遇到这个关键字之后,执行器会停止,函数作用域的状态会被保留。停止执行的生成器函数只能通过在生成器对象上调用next()方法来恢复执行。

  1. 生成器对象作为可迭代对象
  2. 使用yield实现输入和输出
  3. 产生可迭代对象
  4. 使用yield*实现递归算法

3、生成器作为默认迭代器

因为生成器对象实现了Iterable接口,而且生成器函数和默认迭代器被调用之后都产生迭代器,所以生成器格外适合作为默认迭代器。

4、提前终止生成器

1、使用return()终止生成器
2、使用throw()
throw()方法会在暂停的时候提供一个错误注入到生成器对象中。如果错误未被处理,生成器就会关闭。不过如果生成器函数内部处理了这个错误,生成器就不会关闭,还可以恢复执行。

5、生成器小结

迭代是一种所有编程语言中都可以看到的模式。ECMASCript正式支持迭代模式并引入两个新的语言特性:迭代器和生成器。
迭代器是一个可以由任意对象实现的接口,支持连续获取对象产出的每一个值。任何实现Iterable接口的对象都有一个Symbol.iterator属性,这个属性引用默认迭代器。默认迭代器就像一个迭代器工厂,也就是一个函数,调用之后会产生一个实现Iterator接口的对象。
迭代器必须通过连续调用next()方法才能连续获取值,这个方法返回一个IteratorObject。这个对象包含一个done属性和一个value属性。前者时刻一个布尔值,表示十分还有更多值可以访问;后者包含迭代器返回的当前值。这个接口可以通过手动反复调用next()方法来消费,也可以通过原生消费者,比如for循环来自动消费。
生成器是一种特殊的函数,调用之后会返回一个生成器对象。生成器对象实现了Iterable接口,因此可用在任何消费可迭代对象的地方。生成器的独特之处在于支持yield关键字,这个关键字能够暂停执行生成器函数。使用yield关键字还可以通过next()方法接收输入和产生输出。在加上星号之后,yield关键字可以将跟在后面的可迭代对象序列化为一连串值。

十二、原型链

ECMA-262把原型链定义为ECMAScript的主要继承方式。其基本思想就是通过原型继承多个引用类型的属性和方法。

1、构造函数、原型、实例三者的关系?

每个构造函数都有一个原型对象,原型有一个属性指回构造函数,而实例有一个内部指针指向原型。如果原型是另一个类型的实例呢?那就意味着这个原型本身有一个内部指针指向另一个原型,相应地另一个原型也有一个指针指向另一个构造函数,这样就在实例和原型之间构造了一条原型链。

2、盗用构造函数

为了解决原型链包含引用值导致的继承问题,引入了盗用构造函数的概念。基本思路很简单,在子类构造函数中调用父类构造函数,因为毕竟函数就是在特定上下文中执行代码的简单对象,所以可以使用apply()或call()方法,重新创建上下文执行构造函数。
相比于使用原型链,盗用构造函数的一个优点就是可以在子类构造函数中向父类构造函数传参。

3、组合继承

组合继承综合了原型链和盗用构造函数,将两者的优点集中了起来,基本的思路是使用原型链继承原型上的属性和方法,而通过盗用构造函数继承实例属性。这样既可以把方法定义在原型上以实现重用,又可以让每个实例都有自己的属性。
组合继承也保留了instanceof操作符和isPrototypeOf()方法识别合成对象的能力。

作者简介:哪吒,CSDN2021博客之星亚军、新星计划导师、博客专家

哪吒多年工作总结:Java学习路线总结,搬砖工逆袭Java架构师

关注公众号【哪吒编程】,回复1024,获取Java学习路线思维导图、大厂面试真题、加入万粉计划交流群、一起学习进步


下一篇:JavaScript数组你都掰扯不明白,简历上你敢写精通JavaScript?

在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/guorui_java/article/details/123263006

智能推荐

apksigner完成apk的签名_apksigner 签名-程序员宅基地

文章浏览阅读2.3k次。有时候用第三方加固平台加固以后会让我们重新签名。还有就是上应用市场的时候,如果以前该应用已经在市场上上传过了,由于后面业务原因换了开发者账号再去上传就会提示我们去认领一个没有签名的包(unsign.apk),然后去签名上传进行MD5签名验证,如下图看到上面的提示不要慌,不就是加个签名么,apksigner就是SDK自带的签名工具,处于F:\android-sdk\build-tools\xxx目录下将上面的路径配置到系统环境变量path中,打开cmd,切换到unsign.apk目录下,建议.._apksigner 签名

java内省机制及PropertyUtils使用方法_propertyutils.snaketoline(field.getname());-程序员宅基地

文章浏览阅读1.3k次。背景 一般情况下,在Java中你可以通过get方法轻松获取beans中的属性值。但是,当你事先不知道beans的类型或者将要访问或修改的属性名时,该怎么办?Java语言中提供了一些像java.beans.Introspector这样类,实现了在运行时检测Java类并确定属性get和set方法的名称,结合Java中的反射机制就可以调用这些方法了。然而,这些APIs使用起来比较_propertyutils.snaketoline(field.getname());

LeetCode 516. Longest Palindromic Subsequence--最长回文子序列长度_leetcode longestpalindromesubseq连续字符不想等,长度为偶的回文子序列-程序员宅基地

文章浏览阅读536次。Given a string s, find the longest palindromic subsequence's length in s. You may assume that the maximum length of s is 1000.Example 1:Input:"bbbab"Output:4One possible longest palind_leetcode longestpalindromesubseq连续字符不想等,长度为偶的回文子序列长度

Android自定义View之自定义加载进度条(二)-程序员宅基地

文章浏览阅读189次。本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点自定义加载进度条Android自定义View之手把手带你自定义一个进度条上次我们已经把实线和虚线都绘制好了,这次我们就主要来解决更新的问题:怎么随着时间的推移逐渐地绘制进度条怎么在绘制的过程中加速进度条的绘制首先我们来解决第一个问题,也就是随着时间更新我们的..._setvalueinterpolator

c#判断字符串是否json-程序员宅基地

文章浏览阅读5.7k次。来源:https://www.cnblogs.com/cyq1162/p/3841766.html下载地址:  https://github.com/cyq1162/cyqdata/blob/master/Tool/JsonSplit.cs  https://github.com/cyq1162/cyqdata  using System;using System.C..._c#判断是json还是xml

python读取eml文件并用正则匹配邮箱_python 如何查看eml文件-程序员宅基地

文章浏览阅读992次。python读取eml文件并用正则匹配邮箱_python 如何查看eml文件

随便推点

Jquery插件之DataTables初探_jquery datatables 英文-程序员宅基地

文章浏览阅读2.5k次。今天闲来无事,就研究了一下Jquery的DataTables插件。感觉效果不错,支持排序和内容过滤(查询),在这里向大家推荐一下^_^不得不说之前犯了一个错误,这个插件应该叫做DataTable,而我把它当成了tablesort,实在不好意思。。。。。可以直接到官网上去下载下来,单击http://www.datatables.net/到官网上看看,什么API、demo之类的_jquery datatables 英文

算法:逆序对-程序员宅基地

文章浏览阅读8.5k次,点赞8次,收藏11次。逆序对什么是逆序对呢?百度百科这样解释:设 A 为一个有 n 个数字的有序集 (n>1),其中所有数字各不相同。如果存在正整数 i, j 使得 1 ≤ i < j ≤ n 而且 A[i] > A[j],则 <A[i], A[j]> 这个有序对称为 A 的一个逆序对,也称作逆序数。定义:对于一个包含N个非负整数的数组A[1…n],如果有i < j,且A[ i ]>A[ j ],则称(A[ i] ,A[ j] )为数组A中的一个逆序对。例如,数组(3_逆序对

SLAM导航机器人零基础实战系列:(四)差分底盘设计——3.底盘通信协议_slam 实战-程序员宅基地

文章浏览阅读1.2k次。SLAM+语音机器人DIY系列:(四)差分底盘设计——3.底盘通信协议摘要 运动底盘是移动机器人的重要组成部分,不像激光雷达、IMU、麦克风、音响、摄像头这些通用部件可以直接买到,很难买到通用的底盘。一方面是因为底盘的尺寸结构和参数是要与具体机器人匹配的;另一方面是因为底盘包含软硬件整套解决方案,是很多机..._slam 实战

LOJ #6010. 「网络流 24 题」数字梯形-程序员宅基地

文章浏览阅读89次。#6010. 「网络流 24 题」数字梯形题目描述给定一个由n nn行数字组成的数字梯形如下图所示。梯形的第一行有m mm个数字。从梯形的顶部的m mm个数字开始,在每个数字处可以沿左下或右下方向移动,形成一条从梯形的顶至底的路径。分别遵守以下规则:从梯形的顶至底的m mm条路径互不相交;从梯形的顶至底的m mm..._7-60 数字梯形 (110 分) 给定一个由n行数字组成的数字梯形如下图所示。梯形的第一

Ubuntu20.04 + RTX 3090(兼容RTX 2080 Ti) + Pytorch1.7配置方法_2080ti ubuntr20.04-程序员宅基地

文章浏览阅读2.2k次。背景介绍:由于在Ubuntu16.04系统上安装RTX 3090显卡驱动有点吃力(各种Error和不兼容),使用最新Ubuntu20.04系统搭配最新的RTX 3090显卡配置最新的Pytorch【(*^▽^*)】前期准备: 1、Ubuntu20.04下载:Ubuntu20.4_amd64_desktop.iso 2、UNtebootin光盘刻录软件下载:unetbootin,选择Windows下载 3、NVID..._2080ti ubuntr20.04

Struts + Spring +ibatis 整合开发步骤_struts+spring+ibatis-程序员宅基地

文章浏览阅读329次。一.添加Spring 、Struts框架对web.xml文件的修改1. 添加Spring框架2. 在web.xml中引入Spring配置文件(注意:applicationContext.xml文件的路径)context-param> param-name>contextConfigLocationparam-name> param-v_struts+spring+ibatis