当前位置: 首页 > news >正文

【H2O2|全栈】JS入门知识(五)

目录

JS

前言

准备工作

数组API(一)

API概念

数组常见API(一)

arguments

作用域

概念

全局作用域

局部作用域

块级作用域

变量的作用域

作用域链

案例

预解析

概念

变量预解析

函数预解析

案例

对象

概念

优点

属性和属性值

创建对象

遍历对象

结束语


JS

前言

本系列博客主要分享JavaScript的基础语法知识,本期为第五期,包含一些简单的js语法。今天的内容主要包括数组的常用API,作用域,变量,预解析以及对象的相关内容。

与HTML和CSS相比,JS加入了很多逻辑性的元素在里面,所以需要一定的逻辑思维能力,要求能够整合一些知识。如果遇到不理解之处,可以参阅同系列之前的章节。

准备工作

软件:【参考版本】Visual Studio Code

插件(扩展包):Open in browser, Live Preview, Live Server, Tencent Cloud AI Code Assistant, htmltagwrap

浏览器版本:Chrome

系统版本: Win10/11/其他非Windows版本

*我的电脑是Win10的版本,仅供参考*

数组API(一)

API概念

API,英文全称为Application Programming Interface,即应用程序编程接口。 

通常来说,API是软件系统中的一组预定义函数、协议或规则,用于不同软件应用程序之间的通信和数据交换

之前我们知道,可以使用  arr.length  调用数组的长度,类似的,我们也可以使用相同的方式调用数组的API。

不过需要注意,API通常为函数或者方法,因此在调用时不要忘记小括号和必要的参数(如果有)。

数组常见API(一)

今天主要来讲部分常用的数组API,先列在表格里——

API作用
splice(index, number)在数组的index位置开始删除number个元素
splice(index, number, content)在数组的index位置开始删除number个元素,并且替换上content的内容
unshift(item)在数组开头增加指定元素
shift()在数组开头删除一个元素
push(item)压栈,即在数组的末尾增加指定元素
pop()弹栈,即在数组的末尾删除一个元素
slice(start, end)从数组中截取指定左闭右开区间(索引)内的元素
arr1.concat(arr2)在指定的数组的末尾拼接另一个数组
join("separator")将数组转化为字符串,并且在元素之间添加分隔符separator
sort()默认升序排序,元素有多个字符时,取数组元素的第一个字符进行排序

sort(function(a, b) {

        return a - b

})

内置匿名函数进行排序,以 a - b 为正值设置升序排序,此时 b - a 为负值,即设置降序排序
reverse()将数组内容翻转

arguments

arguments是一种类数组,它有数组的索引和长度,但是没有数组的API。

在函数中,arguments是默认有的,可以用来接收任意长度的数组。

作用域

概念

通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。

作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突

在es6之前,JS有两种作用域——全局作用域局部作用域

在es6之后,还有一种作用于 {} 内的作用域——块级作用域

全局作用域

全局作用域指的是所有代码执行的所在的整个环境,通常来说,这个环境是window

局部作用域

局部作用域指的是作用于函数内部的代码环境,所以也可以叫函数作用域。

块级作用域

{} 内定义的某些变量,我们希望它只在 {} 中使用,即在块级作用域里使用。

在es6中,使用let和const声明定义的变量,只能在 {} 中使用。

常见的块级作用域有  if()  for()  等。

变量的作用域

根据作用域的不同,变量可以分为两种——全局变量局部变量

全局变量在代码的任何位置都可以使用,在全局作用域下 var 声明的变量都是全局变量。

特殊情况下,在函数内不使用 var 声明的变量也是全局变量(写法不规范,所以不建议使用)。

局部变量只能在该函数内部使用,在函数内部 var 声明的变量是局部变量。

函数的形参实际上就是一种局部变量。

两类变量的区别是:

  • 全局变量:在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存
  • 局部变量:只在函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块运行结束后,就会被销毁,因此更节省内存空间

作用域链

如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域;

根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链

作用域链的原则为就近原则,即选取最近的元素作为当前使用的元素。

案例

Q:现在,有下面这串代码——

var a = 1;
var b = '11';
function fn1() {var a = 2;var b = '22';fn2();function fn2() {var a = 3;fn3();function fn3() {var a = 4;console.log(a); //a的值 ?console.log(b); //b的值 ?}}
}
fn1();

请问输出的a和b的值是多少?

A:我们使用一张图来分析上述代码的作用域链——

所以,输出应当是4和'22'。

Q:对于下面的代码,输出的值应当是多少?

var a = 10function fn1() {var a = 20fn2()
}function fn2() {console.log(a)
}

A:对于  fn2()  而言,虽然它在  fn1()  中被调用了,但是实际上它是被声明在全局中的,所以作用域是window,因此输出值为10。

预解析

概念

JavaScript 代码是由浏览器中的 JavaScript 解析器来执行的。

JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析代码执行

  • 预解析:在当前作用域下, JS 代码执行之前,浏览器会默认把带有 var 和 function 声明的变量在内存中进行提前声明或者定义,预解析也叫做变量提升函数提升
  • 代码执行: 从上到下执行JS语句。

注意:预解析会把变量和函数的声明在代码执行之前执行完成。

变量预解析

变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升

函数预解析

函数的声明会被提升到当前作用域的最上面,但是不会调用函数。

案例

Q:对于下面的代码,输出的结果是什么?

console.log(num)
var num = 10fn1()
function fn1() {console.log('打印')
}fn2()
var fn2 = function() {console.log('想不到吧')
}

A:由于变量的值不会提升,所以第一个是默认var num但是未赋值,结果为输出undefined

由于命名函数可以提升,相当于在fn1()之前实质上已经声明函数并在该语句完成调用,结果为输出打印

匿名函数相当于变量,该段代码执行之前,会做变量声明提升,fn在提升之后的值是undefined;而fn调用是在fn被赋值为函数体之前,此时fn的值是undefined,所以无法正确调用,结果为报错 fn is not a function

对象

概念

在 JavaScript 中,对象是一组无序的相关属性方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。

  • 属性:事物的特征,在对象中用属性来表示(常用名词表示)
  • 方法:事物的行为,在对象中用方法(函数)来表示(常用动词表示)

以一部手机为对象,那么它的属性和方法应当是——

优点

保存一个值时,可以使用变量,保存多个值(一组值)时,可以使用数组。

如果要保存一个人的完整信息呢?

例如,将“张三”的个人的信息保存在数组中的方式为——

var arr = [‘张三’, ‘男', 128, 154]

上述例子中用数组保存数据的缺点是:数据只能通过索引值访问,开发者需要清晰的清除所有的数据的排行才能准确地获取数据,而当数据量庞大时,不可能做到记忆所有数据的索引值。

为了让更好地存储一组数据,对象应运而生:对象中为每项数据设置了属性名称,可以访问数据更语义化,数据结构清晰,表意明显,方便开发者使用。

如果使用对象来表述上述信息,应当如下——

var obj = {"name":"张三","sex":"男","age":128,"height":154
}

属性和属性值

对象中包含了表达这个具体事物(对象)的属性和方法,采取键值对的形式表示。

  • 键:相当于属性名,即对象中存储具体数据的项
  • 值:相当于属性值,可以是任意类型的值(数字类型、字符串类型、布尔类型,函数类型等),对象方法即对象中存储函数的项

比如,之前在为张三设置名字属性时,使用的就是下面的键值对——

name: "张三",

这里也给一个值为函数的情况吧——

sayHello : function(){alert('大家好啊~');}

访问对象的属性

  • 对象里面的属性调用 : 对象.属性名 ,这个小点 . 就理解为“ 的 ”
  • 对象里面属性的另一种调用方式 : 对象[‘属性名’],注意方括号里面的属性必须加引号 

示例代码如下——

console.log(obj.name)     // 调用名字属性
console.log(obj['name'])  // 调用名字属性

调用对象的方法

  • 对象里面的方法调用:对象.方法名() ,注意这个方法名字后面一定加括号
  • 也可以利用函数名调用

示例代码如下——

obj.fn()
obj["fn"]()

小结

属性是对象的一部分,而变量不是对象的一部分,变量是单独存储数据的容器

  • 变量:单独声明赋值,单独存在
  • 属性:对象里面的变量称为属性,不需要声明

方法是对象的一部分,函数是单独封装操作的容器

  • 函数:单独存在的,通过“函数名()”的方式就可以调用
  • 方法:对象里面的函数称为方法,方法不需要声明,使用“对象.方法名()”的方式就可以调用 

创建对象

创建对象通常来说有三种方式——字面量new构造函数

使用字面量创建

使用字面量创建的参考代码如下——

var obj1 = {}

这种方式在创建时即可添加属性和属性值,示例代码如下——

var obj = {name : 'pink',age : 18,sex : '男',sayHello : function(){alert('大家好啊~');}
};

使用new Object()创建

该方式用于创建一个空的对象,参考代码如下——

var obj2 = new Object();

实质上,Object()内置了一个构造函数,利用构造函数创建了一个新对象。

为该方法创建的对象赋值的方法示例如下——

obj2.name = 'pink';
obj2.age = 18;
obj2.sex = '男';
obj2.sayHello = function(){alert('大家好啊~');
}

注意以下三个要点:

  • Object() :第一个字母大写
  • new Object() :需要 new 关键字
  • 使用的格式:对象.属性 =  值;

使用构造函数创建

构造函数:是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new 运算符一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。

使用构造函数的封装格式如下——

function 构造函数名(形参1,形参2,形参3) {this.属性名1 = 参数1;this.属性名2 = 参数2;this.属性名3 = 参数3;this.方法名 = 函数体;
}

使用构造函数调用的参考代码如下——

var obj3 = new 构造函数名(实参1,实参2,实参3)

以上代码中,obj即接收到构造函数创建出来的对象。

注意事项

  • 构造函数约定首字母大写
  • 函数内的属性和方法前面需要添加 this ,表示当前对象的属性和方法。
  • 构造函数中不需要 return 返回结果
  • 当我们创建对象的时候,必须用 new 来调用构造函数
  • 构造函数,如 Stars(),抽象了对象的公共部分,封装到了函数里面,它泛指某一大类(class);创建对象,如 new Stars(),特指某一个,通过 new 关键字创建对象的过程我们也称为对象实例化 

new关键字的作用

  • 在构造函数代码开始执行之前,创建一个空对象;
  • 修改this的指向,把this指向创建出来的空对象;
  • 执行函数的代码
  • 在函数完成之后,返回this---即创建出来的对象  

遍历对象

for...in 语句用于对数组或者对象的属性进行循环操作。

示例代码如下——

for (变量 in 对象名字) {// 在此执行代码
}

语法中的变量是自定义的,它需要符合命名规范,通常我们会将这个变量写为 k 或者 key

遍历对象获取属性和属性值的示例代码如下——

for (var k in obj) {console.log(k);      // 这里的 k 是属性名console.log(obj[k]); // 这里的 obj[k] 是属性值
}

扩充知识

我们知道,数组实质上也是一种对象,所以我们也可以用相同的 for ... in 方式对数组进行遍历——

for (var i in arr) {console.log(arr[i])
}

此时的i是索引值

此外,我们还可以使用 for ... of 方式对数组进行遍历——

for (var item in arr) {console.log(item)
}

此时的item是数组中的元素

结束语

本期的内容到这里就结束了,主要是js的数组的常用API,作用域,预解析以及对象的相关内容。在后续的本系列博客中,我会继续更新js的基础语法知识,并适当地配合上一些案例。

在全栈领域,博主也只不过是一个普通的萌新而已。本系列的博客主要是记录一下自己学习的一些经历,然后把自己领悟到的一些东西总结一下,分享给大家。

文章全篇的操作过程都是笔者亲自操作完成的,一些定义性的文字加入了笔者自己的很多理解在里面,所以仅供参考。如果有说的不对的地方,还请谅解。

==期待与你在下一期博客中再次相遇==

——还在漏气的【H2O2】


http://www.mrgr.cn/news/55654.html

相关文章:

  • linux file结构体与inode结构体
  • Linux系统安装软件的4种方式【源码配置编译安装、yum安装、rpm包安装、二进制软件包安装(.rpm/.tar.gz/.tgz/.bz2)】
  • vue3使用ref动态获取组件,并对动态表单组件进行校验
  • 【设计模式七大设计原则】
  • 礼想视界,期待与您携手共创影视未来!
  • 200台设备如何做到运行半年0故障?工厂设备管理这些环节是关键!
  • 碰到这个问题请更新或重新安装fastapi版本
  • 时序分解 | Matlab实现EEMD+SE集合经验模态分解+样本熵计算的时间序列信号分解
  • Android 性能之 Game Mode
  • 基于微信小程序的驾校预约系统设计与实现
  • P3924 康娜的线段树
  • 2025医药化工水处理新技术、新工艺、新装备发展论坛3月4日济南举办
  • 【VUE小型网站开发】优化通用配置
  • 【Docker技术详解】(一)Docker镜像文件系统的关系和交互
  • 27.3 一致性哈希算法介绍
  • 142 环形链表II
  • Vim使用与进阶
  • 168K+ Star!AutoGPT:一个构建、部署和运行AI代理的强大平台
  • 【D3.js in Action 3 精译_037】4.1 DIY 实战:D3 源码分析之——d3.timeFormat() 函数
  • 【AI学习】扩散模型学习总结PPT
  • python 爬虫 入门 四、线程,进程,协程
  • Mysql常见面试题总结
  • 深入理解Oracle闪回技术
  • JMeter快速入门示例
  • pycharm中使用ctrl+鼠标滚轮改变字体大小
  • 深入探秘ReentrantLock的实现与应用:从底层原理到业务场景的实践