因此,本文主要还是针对 运行在浏览器上的 JS 情况。
大家在这里,一定要明白一点:
JS 是运行在浏览器上的。
JS 很多的功能都是浏览器给它提供的能力。
这就好比,我们Java是运行 JVM 上的,java的很多能力都是 JVM 提供的。
===================================================================
此时,JavaScript的最简单的一个程序,输出 hello world就完成了。
具体是通过 alert 函数进行弹框来实现的。
这个 alert,可以视为是浏览器提供的一个 BOM API 之一。
另外,js 里面的语句后面的 分号,不是必须的。
可写可不写。
但是建议:还是写上。
1、内嵌式
也就是把 js 写到 script 标签中。
我们下面的讲解主要就是用这一种方式。
2、行内式
把 js 写到 HTML 元素的内部
3、外部式
把 js 写到一个单独的 .js 文件中,再通过 script0 标签来引入。
这种方式,是实际开发中最长用的一种引入 js 代码的方式。
因为这种方式,可以把 js 代码分成多个文件来去分别表示。
但是本篇博文主要还是以内嵌式为主。
因为写起来简单,而且我们目前写的代码就不难。
拓展:
如果 script 标签中,既有 src 属性,内部又有 JS 代码,会怎么样?
就会导致里面的代码不会被执行的效果。
如果你想要全部输出,只能将其拆分成2个script标签,来分别执行。
JS 和 用户交互,不止弹窗这种方式。
还有很多其它的方式。
输入: prompt
弹出一个输入框
这个操作,类似 Java 语言的 Scanner 。
但是在实际开发中,很少会用到,比较小众。
因为我们可以借助 input 标签进行输入,借助用户点击按钮也能进行输入。
输出: alert
这个就过了
输出:console.log
在控制台打印一个 日志(供程序员看)
这个是开发中,最常用的一种输出方式。
主要是因为 alert 弹框,体验并不好。
这就好比,你在看剧,突然弹个广告。
你还得必须看完。
你说,难不难受?
弹框也是一样,弹出框,你就必须要处理。
否则,无法进行其他的页面操作。
我们在写代码,后者调试代码的时候,一般就会通过 console.log 来打印。
console.log 会把 日志给输出到控制台中。
注意!这个控制台不是电脑系统的控制台,而是 浏览器开发者工具中的标签页中的控制台
下面来看一下,调用 console.log 的效果是如何。
同时 console.log 不仅仅能打印日志,还能打印一些错误。
错误:
1、 JS 代码中的语法错误
2、JS代码运行时错误
这两种错误,都会在控制台中显示出来。
==============================================================================
JavaScript 虽然一些设计理念和 Java 相去甚远, 但是在基础语法层面上还是有一些相似之处的。有了 Java 的基础很容易理解 JavaScript 的一些基本语法。
接下来的介绍,如果是和 Java一样,我就快速通过。
重点讲 和 Java 不一样的地方。
定义一个变量
格式: var 变量名 = 初始值;
你会发现:不管你创建的变量是什么类型,此时都是统一使用 var 这个关键字来表示的。
至于你变量具体是什么类型,取决于初始化的值是什么类型。
有的人可能较劲,你是不是少写一个浮点型数据?嗯?
这是因为 JS 是不区分 整形 和 浮点型数据的。
统一认为是数字类型的数据。
另外,JS的变量可以不初始化,但是不初始化的时候,变量是一个特殊的值:“undefined”,类型也是 undefined。
但是!你不能创建一个未初始化的变量,同时指定它是一个 字符串 / 数字 / 数组 类型。
这种操作是不被允许的!!!!
小拓展:
其实,这种风格的写法,是更主流的。
更多的编程语言是这样设定的。
包括像 C++,Go 这些语言,也支持上述类似的写法。
使用变量
这个没啥说的。
和 Java是一样的。
1、读取
2、修改
但是!说是一样,但还是有一个地方有着很大区别的。
就在于“修改”!
如果 a 本来是一个 数字类型,在赋值的时候,可以给它赋一个数字类型,也可以赋一个字符串类型,也可以赋一个数组类型…
总得来说,你可以给它赋任意类型的数据。
此时,a 变量的类型,就会随之发生改变。
比如:
a 是数字类型的变量,我给它赋一个 字符串的数据,这是可以成功的。
而且 a 变量的类型 也变成了字符串类型。
因此,得出一个结论:变量的类型,可以在运行的过程中,随着赋值而发生改变。
这种行为,称为“动态类型”’。
动态:运行时
像 Java 这种语言,是不支持这种 运行时 类型发生改变的情况。
Java的这种行为,被称为“静态类型”
支持“动态类型”的编程语言还有:Python,PHP,Ruby…
支持“静态类型”的编程语言还有:C/C++,Go,Rust…
有的人可能基础扎实,认为 Java 也是支持 动态类型。
因为 Java 里面存在着 很多类型转换的方法。
注意!如果你有这种想法,那么你的Java基础肯定是有缺陷的!
你要明白Java类型转换,是将一个类型的值,转换后(旧的变量类型没有发生改变),赋给一个新的,并且与转换后的数据类型是对应的变量对象。【不然是进行转换的,必须类型是对应的】
而 JS 初始化 确定了 var 的类型,将一个与初始化指定类型,不相符的类型数据,强行塞给它。
非但没有出现类型的排斥,反而还把 var 初始化指定的数值类型给改变了!!
由此,就能看出 js 和 java ,关于 变量修改的区别了。
从侧面来思考,为什么写 var,而不是去写一个具体类型?
因为 它的类型老变嘛,你一开始是整形,回头它就给一个 字符串。
整形 对 字符串,大眼瞪小眼,不就很尴尬嘛。。。
拓展:动态类型 和 静态类型 谁更好?
其实最开始的时候,这个是有争议的。
但是,随着时间的推移,至现今。
在 2022 年,这样视角来看待,静态类型的阵营完胜!
现在业界基本达成共识,认为静态类型比动态类型更好!
因为静态类型,编译器就可以做更多的检查,让有些 问题/错误 被提前发现了。
开发工具(IDE),也可以基于类型做更多的分析,提供更加丰富的支持。
当然不是说,动态类型就没有优点!
动态类型的优点:
1、代码更灵活。
2、用最少的代码,解决复杂的问题
比如:
写一个函数,就可以同时支持多种不同的类型参数。
完全不需要“重载 / 泛型”,这样语法。
因为 JS 天生就自带这种功能。
虽然有这个优势,,但是整体来说,利大于弊。
静态类型,哪怕说我多写一点 泛型 / 重载 类型的代码,也不要紧。
因为我的编译器都有充分的检查,所以我写完之后,也不会特别慌。
但是要是动态类型的话,很可能你写完代码,都不知道它对不对。
因为无论你输入什么样的参数,它都能接收。
因此,只要你一个参数错了,可能你就要在电脑面前坐几天。
在动态类型的语言中,Python 已经发展一些 “投敌”的苗头了。
本来 Python 也是 js 差不多。
a=10 都不带类型的。
现在Python 支持这种写法:a:int = 10
可以显式的去声明一个类型类。
但是!有一个点,需要补充。
随着时间推移,关于 JS 变量的类型,出现了一个新的类型 let。
而且,现在更倾向于 使用 let 来 代替 var。
下面,我们就来看一下 let 的效果。
从效果上来看,var 和 let 的效果是一样的。
但是我们更倾向于使用 let ,为什么呢?
这是因为 var 是 旧版本(早期的设计),有很多的地方,其实是违背直觉的!
比如,下面的这个例子
得出结论: var定义的变量,并不会收到大括号的限制。【作用域不会被限制】
我们再来看下面 let 定义的变量 的表现。
var 和 let,还有很多的一些小细节。
这里就不一样列举了。
总得来生活 let 要比 var 更符合我们程序员的直觉。
JS 中内置的几种类型
number: 数字. 不区分整数和小数.
boolean: true 真, false 假.
string: 字符串类型.
undefined: 只有唯一的值 undefined. 表示未定义的值.
null: 只有唯一的值 null. 表示空值
上面三个类型,这个相比大家都很熟悉。
而下面的两个类型,就是独属于 js 了。
undefined:可以作为一个类型,同时表示唯一的值,也是 undefined。表示这个变量没有被定义;或者这个变量定义了,但是没有赋予初值的情况。
null:表示控制,虽然也是表示唯一的值,但是与 undefined 还有一定区别的。
而且这个空值 和 Java中 空值也是不一样的。
Java中的空值,是一个 Object 类型的。
而 JS 的空值的类型,和 undefined的情况一样,与表示的值一样,也是null类型。
数字类型
像下面这种,8,16,2进制数,在Java也是支持的。
let a = 07; // 八进制整数, 以 0 开头
let b = 0xa; // 十六进制整数, 以 0x 开头
let c = 0b10; // 二进制整数, 以 0b 开头
特殊数字值
Infinity: 无穷大, 大于任何数字. 表示数字已经超过了 JS 能表示的范围.
-Infinity: 负无穷大, 小于任何数字. 表示数字已经超过了 JS 能表示的范围.
NaN: 表示当前的结果不是一个数字.
需要注意的是 负无穷大,不是负无穷小。
负无穷小,表示的是一个无限接近于 0 的数、
负无穷大,是指无穷大的相反数
但是,这两个比较少见。
见的最多的还是 NaN。
NaN:Not a Number - 不是一个数字
什么时候会出现 NaN ?
如果 运算结果,得到的不是数字的值,就会出现 NaN。
但是!如果我们把减法换成加法,这就不一样了!
效果就和 Java一样,会起到一个字符串拼接的作用。
另外, JS 中 提供了一个 isNaN的方法,用于判断 得到数据是否是一个数字。
返回数值类型 是 布尔类型。
如果是数字,返回false
反之,返回true
字符串类型
字符串类型,这里的很多操作和Java是类似的。
首先,字符串 可以通过单引号定义,也可以通过双引号定义。
如果字符串本身就包含了 引号,这种情况是被允许的。
这个时候,就可以通过 单双引号 灵活搭配的形式,来避免使用转义字符。
JS中的转义字符,不仅仅是 +单双引号,还有其它的转义字符,也是支持的。
像 \t(水平制表符),\n(换行符),\f(换页符)…这些转义字符,也是同样支持的。
字符串求长度
JS 求字符串长度,是通过 length 属性。
Java 里面求字符串长度,是通过 length() 方法。
字符串拼接
可以通过直接使用 + 号,来进行拼接。这里和 Java 是一样的。
另外字符串提供很多方法
很多方法想必,大家都很熟悉。
这里 三分之一的方法 都是Java里面有的。
其它方法,有兴趣的可以自己尝试一下。
boolean 布尔类型
与Java的boolean类型不同,
JS 中的 布尔类型,会当成 0 和 1 来处理。
而Java的 boolean 类型,取值能使 false 和 true,绝对不会和数字扯上关系的。
上面的代码中,js 把 true 当成 1 来处理了。
这种设定方式,认为其实并不科学!
其中涉及到 隐式类型转换,因为 隐式类型转换 本就是不科学的设定。
有一种说法:
如果一个编程语言,越支持隐式类型转换,就认为类型越弱。
如果一个编程语言,越不支持隐式类型转换,就认为类型越强。
Java,Go,Python 认为是强类型的编程语言
C,JS,PHP 认为是弱类型的编程语言
注意,静态类型 / 动态类型 vs 强类型 / 弱类型
这两者是没有关系的,是两个不同的体系。
那么,弱类型 vs 强类型,谁更好呢?
肯定是 强类型。
因为强类型,就意味着类型之间的差异更大,界限是更明确的。
代码在类型上出现问题,也是最容易锁定位置的。
如果是弱类型,意味着类型之间的差异不大,界限是更模糊的。
代码在类型上出现问题,是最难看出来的。
因为它什么参数都是可以接收的。
就是代码能跑,但是效果不对。
这就很麻烦!
undefined 未定义数据类型 && null 空值类型
这个类型的变量,是 JS 的一种特殊情况。
undefined 这个类型,就只有 undefined 这一个值。
我们再来看看 null 空值类型。
另外,空值也有一些特殊情况。
JavaScript 中的运算符和 Java 用法基本相同. 此处不做详细介绍了
算术运算符 - 不同点
+ - * / %
这里的不同点,体现在 除法: /
但是!大部分编程语言,1/2 => 0
只有极少部分的编程语言【(JS,Python3(Python2不是),Dart】,1 / 2 == 0.5
赋值运算符 & 复合赋值运算符
=
+=
-=
*=
/=
%=
自增自减运算符
++: 自增1
–: 自减1
比较运算符 - 不同点
< 小于号,>大于号
<= 小于等于,>= 大于等于
这几个就不用多说了。
重点在于,比较 相等/不相等 的 符号。
JS中比较相等的符号,有两种:
== 和 ===
不相等的符号也有两种:
!= 和 !==
== 和 != 是一组风格、
=== 和 !== 是一组风格。
先说, == 和 != 这一组。
只是比较两个变量的值,不比较 两个变量的类型。
如果两个变量能够通过隐式类型转换,转换相同的值,
那么,此时就认为 两个变量 是相等的。
再来看,=== 和 !== 这一组。
既要比较 两个变量的值,又要比较两个变量的类型。
如果类型不相同,就直接认为两个变量不相等。
比较的过程中,就不存在隐式类型转换的说法。
注意哦!这里和 java的 equals 是不一样的!
equals 是 比较值。
== 是比较身份。
而且 equals 涉及到对象的比较。
谈到对象的比较,有三个维度的比较
1、比较身份(比较地址,看是不是同一个对象)【JS中没有比较身份的函数】
2、比较值(标对对象中存储的数据是否相同)
3、比较类型(两个对象的类型是否是同一个类型)
而且 Java中 equals 是可以被重写的。
equals 不重写,默认也是比较身份。
可以以通过重写 来设定成 比较值。
在Java中的 instanceOf 就是比较类型的。
所以,以后在写 JS 代码的时候,遇到比较相等的时候,请慎重对待!!!
逻辑运算符 - 不同点
用于计算多个 boolean 表达式的值.
&& 与: 一假则假
|| 或: 一真则真
!: 非
&& || ,这两个行为,和Java中 && 和 || 差别就挺大的。
Java 中的 && 和 || 行为非常简单!
效果就是返回一个布尔类型的值: true,或者 false。
而 JS 中的 && 和 || ,返回是其中的表达式。
if 语句
if 语句 执行条件就是 条件表达式为 true.
这个就不细讲了,和Java一模一样。
// 形式1
if (条件) {
语句
}
// 形式2
if (条件) {
语句1
} else {
语句2
}
// 形式3
if (条件1) {
语句1
} else if (条件2) {
语句2
} else if .... {
语句...
} else {
语句N
}
三元表达式
格式:条件 ? 表达式1 : 表达式2
如果条件为真,返回表达式1。
如果条件为假,返回表达式2。
switch
更适合多分支的场景
switch (表达式) {
case 值1:
语句1;
break;
case 值2:
语句2:
break;
default:
语句N;
}
循环语句
重复执行某些语句
while 循环
while (条件) {
循环体;
}
continue && break
continue:结束这次循环,进入下一次循环。
break:直接跳出循环,终止运行。
let i = 1;
while (i <= 5) {
if (i == 3) {
i++;
continue;
}
console.log("我在吃第" + i + "个李子");
i++;
}
for 循环
for (表达式1; 表达式2; 表达式3) {
循环体
}
`表达式1: 用于初始化循环变量.
表达式2: 循环条件
表达式3: 更新循环变量``
创建数组
1、使用 new 关键字创建
和 Java 创建数组很像,但不完全一样。
更像 Java中创建对象的写法。
注意!这种写法很少用,因为比较麻烦。
2、使用字面量方式创建 [常用]
这里就和Java差别很大。
Java 定义一个数组的时候,通过关键字 new,并标明类型,以及容量,才能创建。
Java 针对数组初始化,是使用大括号来将元素括起来。
而JS定义一个数组的时候,不需要声明数组类型,以及容量。
JS 针对数组初始化,使用的是中括号,将元素括起来。
而且,我们 JS 数组,还可以像下面这么写。
什么类型的元素,都可以往里面放。
这是 Java 普通数组所做不到的,需要借助数据结构才能实现。
但是 一般也不是这么用,都是会指定一个类型放入数组中。
有的人可能会问:这是一个什么类型的数组?
我只能说兄弟们格局小了!
没有什么类型,这就是一个数组。
在 JS 中,只有一种数组,就叫做数组,里面的元素可以是不同类型的!
另外,JS 中数组,是不分类型的,并且无法强制要求数组只能放入一种类型的数据。
要想数组里存入的都是同一种类型的数据,就只能通过“人为”的方式去完成。
就是 你给这个数组的元素都是 同一种类型的。
而且,还没完!
JS 中数组的元素,还可以是数组类型的元素。
是不是颠覆各位的认知了。
其实这都是基操,动态类型的语言都是这么玩的。
比如:Python,PHP等等…
但是 Python 已经有“投敌”的苗头了、
在 Python中,有一个这样的写法:arr:List[int]
这种写法的意思,就是要求这个元素必须是整数了。
打印数组
JS 中直接通过 console.log 就可以打印数组的内容。
这要比 Java方便的多,Java要输出一个数组的元素的方法。
1、循环打印数组元素
2、通过 Arrays.toString(数组名)来实现打印数组元素
获取数组元素
JS 也是通过下标来获取元素。
下标也是从 0 开始计算的。
前方高能预警!
将会彻底打破我们对数组的常规理解。
按照之前的理解,在Java中要求数组下标,是 0 - 数组长度-1。
如果 超出这个范围,就会抛出一个数组越界异常。
但是,在 JS 中,就不是这样了!
下面的代码,就更狠了。
还没完,还有一个变态操作。
可能大家对 -1 看作是一个 属性 / 键值对 的感触不是很深,再来一个操作,帮你们加强一下印象,嘻嘻。。。
总得来说,JS 的数组,就不是一个正经的数组。
除了能接数组的活,还能接 Map 的活(表示键值对)。
进一步的来说,与其说数组是 Map,不如说是一个“对象”。【这是更准确的说法】
在JS里,是可以在运行时,给对象新增属性的。
arr[‘hello’] = 10,这个操作其实就是在给 arr 这个对象,新增了一个属性。
属性的名字是hello,属性的值是 10
这些语法都不是 JS 独有的,动态类型的语言都是这样设定的。
PHP 的设定方式 几乎和 JS 一模一样。
Python 略有差异,但是本质不变。
上述的代码,相比对后端的朋友,产生了一万点暴击。
其实这些都是属于 “静态类型” vs “动态类型”,两个流派之间的碰撞。
这两个流派之间的语法,是有很大区别的。
但其实 JS 和 Java 的 差别,并没有到难以接受的程度。
如果大家未来了解一下“函数式编程语言”(lisp,erlang,Haskell…),那才是真的难受,远超 js。
整个编程思路都变了。
你能想象一下,当你接触到这个编程语言,它告诉你,“对不起,我们这语言不提供变量。只有常量。而且我们这里的代码不支持你好好写代码,支持你动不动就递归。”
请问碰到这种语言,你是什么感受?
虽然不提供 变量,但是有常量。
换个角度,你可以认为“函数式编程语言”,不允许你修改变量的值。
和 String类型的变量相似,想修改,只能搞个新的、
另外,小拓展一下。
递归,发挥的不是计算机的性能,而是人脑的性能。【我们想象递归的过程】
人脑其实更适合思考递归的。【指数学思维能力强的人】
计算机在执行这些函数式语言的递归过程中,往往要借助尾递归进行优化。
把递归转成循环代码来执行。
递归的本质就是 数学的递推公式。
JS数组中的一些后续操作
获取数组的长度
通过 .length 就能获取到
JS 中 length 属性是可以改的!!!!
在Java中,这种操作是想都不敢想的!!!
原码,你怎么改?
下面,我们就来看看看 length属性,是怎么改的。
效果很明显,不但数组长度变成了 3,而且 元素也被删除了。
如果,我们把 数组长度改成 5 呢?
往数组中新增元素
最常见的插入操作,是通过 push 方法,能够给 数组末尾 追加一个元素。
就相当于 Java 中 ArrayList 里面的 add 操作。
删除数组中的元素
JS中删除数组中的元素,所依赖的方法,非常nb。
叫做 splice,这个方法,准确的说是针对 数组中的某讴歌片段,进行替换。
所以,这个方法既可以用来插入元素,又可以用来删除元素。
删除操作
替换操作
数组里面其实还有很多其他方法,有兴趣的可以去自己琢磨琢磨。
首先,大家要明白,JS中的函数(function),在 Java中 叫做 方法(Method)。
注意!函数就是方法,方法就是函数,两者就是同一个东西,只是叫法不同而已。
通常情况下,不去考虑这两个概念的区别。
但是如果非要考量,可以这么理解:
函数,是和 “对象” 独立开来的代码片段。
而方法,是依托与 “对象” 的代码片段。
函数一般不会与 “对象” 绑定在一起,而方法一般是与 “对象” 绑定在一起。
因此方法,可以认为是成员函数。
成员函数:可以认为函数里面的一种具体的形态。
在类里面写的,与 “对象” 相关的成员函数,将其称为 方法。
在 Java 中,由于本身这样的代码片段都是依托于类和对象的,就没有这种独立的函数。
因此,Java中就都是方法。
也印证了Java的一句话:万物皆对象。
相对于 JS,JS 中的方法,大多数都是脱离对象存在的,所以称为函数。
语法格式
// 创建函数/函数声明/函数定义
function 函数名(形参列表) {
函数体
return 返回值;
}
// 函数调用
函数名(实参列表) // 不考虑返回值
返回值 = 函数名(实参列表) // 考虑返回值
注意!在 创建函数/函数声明/函数定义 的时候,形参列表不用写形参类型。
其实也很好理解,因为 JS 是动态类型的语言,你写了类型都不好使!
形参的类型,完全取决于程序运行时,你给函数传的什么参数。
同样的, 函数也不必写返回值类型,因为没意义。
其它的就没什么好说的。
再来看函数调用
实参列表 要与 形参列表匹配。
同时也通过一个变量来接收 函数的返回值
下面先看看 不带参的函数的定义和调用
我们再来看看带参方法的定义 和 调用
函数表达式
在 JS中,函数是 “一等公民”。
一等公民:一个“一等公民”的函数,函数可以像一个普通的变量一样,赋值给 其他的变量。同时,可以作为另一个函数的参数,还可以作为另一个函数的返回值。
简单来说:函数和普通的变量,并没有本质区别。
只不过函数这个变量,相对于普通变量来说,多了一个功能(可调用)。
所谓的函数表达式,其实就是把一个函数赋值给一个变量了。
这里讲的比较浅显,其实还可以更复杂的来讲。
让一个函数 返回另外一个函数,在返回函数的同时,不光是返回函数本身,还返回了这个函数依赖的上下文,这个时候就构成了闭包。
只是知道有这么回事,并不做深入。
作用域
某个标识符名字在代码中的有效范围.
在 ES6 标准之前, 作用域主要分成两个
全局作用域: 在整个 script 标签中, 或者单独的 js 文件中生效.
局部作用域/函数作用域: 在函数内部生效.
上面提及到 ES6,是 JS 的版本。【最新的版本,已经是 ES十几】
之所以称为 ES6,是因为 JS 原名是 ECMAScript,简称ES。
故 JS 的版本都是使用 ES数字,来进行表示的。
这个就类似于 Java 的版本。
我们主要学习的是 Java 8(jdk1.8),Java 最新的版本已经到 18 了。
这里的 ES6 和 Java8,都是属于 JS 和 Java 中的应用最广泛的大版本。
其实在 ES6 之前,就没有 let 这个东西。
let 是在 ES6之后 才引入的。
也就是说,在ES6版本之前,只有 var。
即 变量 只会被函数划分作用域,而函数里面的代码块,是不会影响到作用域的。
也就是说,在ES6之前,只有 全局 + 函数 作用域,没有块级作用域(大括号挂起来的区域)。
这个是前讲过的。
但是这一点,其实在我们的后续,有了ES6之后,也就是有了 let 之后。
这个东西也就发生了改变,也就是有了 块级作用域。
一个变量在{}内部定义,是无法被大括号外部访问。
即便如此,JS 和 Java的作用域,还是有区别的。
在 JS 中,{}内部代码 是可以访问 {} 外部的代码的。
在上图的例子中,如果你们想要强行访问 外面的 num 值。
只能通过 给 hello2 加个形参,然后调用的时候,把 num 作为 实参来传进来。
修改 hello2的num值。
此时, hello2中的num值,就是外面 num的值了。
【注意!想直接外面的num值,是不可能的!】
另外,说一点。
尤其是学Java的朋友,当你们产生使用 this ,这个想法的时候,就非常危险了。
因为 JS 的函数中,确实能用 this。
但是,这个 this非常危险!
它有着一系列复杂的规则,来决定 this 的 指向。
就是说,JS 的 this,不像 Java中那样是固定指向的。
JS的this,是会改变指向了。
基本概念
对象,就是一些属性 和 方法的集合。
这个概念,与传统意义上的Java对象的概念是类似的。
但是有一个比较大的区别。
在 Java中,我们的对象是需要先有类,然后针对类进行实例化才能产生对象。
等于就是说,类就是一个模具,可以批量生产相同规格的产物。
而在 JS 中,对象 是不依托于 类的。
就是说:在 JS 中,无需借助类,就能创建一个对象。
另外,Java 中的类,可以视为是一种 自定义类型的类。
例如: Cat 类 和 Dog 类,是两个不同类型。
但是在 JS 中,所有的对象,都是一个类型【object类型】。
创建对象 && 对象的使用
很简单,直接通过 {} 的方式,就可以创建对象。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// {} 就是 一个 匿名对象
// 将这个对象赋予 变量 student
let student = {
// 属性
name: 'cxk',
age: 20,
height: 178,
weiight: 120,
// 方法
sing: function(){
console.log('鸡你太美')
},
jump: function(){
console.log('一段舞蹈');
},
};
</script>
</body>
在 js 对象中,我们可以很直观的看到 js的对象是有方法 和 变量。
js的对象,与其说是一个对象,不如说是一个 键值对 结构 更加合适。
js对象中的每个属性和方法,其实都是通过“键值对” 这样的方式来表达的。
{} 表示这是一个对象
键值对之间,采用 逗号 进行分割。
键和值之间,采用 冒号 进行分割。
定义出这样的一个对象之后,我们就可以采用 student.属性名 / 方法名 的方式 来进行访问了。
上面创建的对象的方式,是属于 使用字面量创建对象。
在JS 中,还有两种创建对象的方式。
第二种: 使用 new Object 创建对象
通过创建一个 Object的空对象,再把创建好的对象赋予 一个变量。
通过 变量名.属性名 = 值 的方式,进行动态创建对象属性。
在 JS 中,一个对象里面有哪些成员,也是动态可以改变的。
也就是说,假设本来 这个对象只有 2个属性(name 和 age),但是执行代码之后,感觉还可以加上一些属性,通过 变量名.属性名 = 值 的方式,就可以添加新的属性。
更不用说,可以去修改属性的值了。
let student = new Object(); // 和创建数组类似
student.name = "蔡徐坤";
student.height = 175;
student['weight'] = 170;
student.sayHello = function () {
console.log("hello");
}
第三种:使用 构造函数 创建对象。
当前我们所说的构造函数,其实是一种特殊的函数。
该构造函数,目的是为了 批量的创建出一组 类似的对象。
function 构造函数名(形参) {
this.属性 = 值;
this.方法 = function...
}
let obj = new 构造函数名(实参);
注意!对象里面 的 属性和方法,是通过 this. 的方式来创建的。
换个说法,当我们看到函数内部,通过 this.方式来创建属性和方法的时候,此时这个函数大概率就是构造函数了。
使用的时候, new + 构造函数名 +(实参)的方式来使用的。
这个就跟Java的带参的构造方法很相似。
其实 JS 中后两种创建对象的方式,其实JS自己也觉得别扭的。
所以,现在我并不建议大家使用后面两种方式来创建对象。
更推荐使用第一种方式来创建对象。
因为毕竟 JS 并没有引入类 这样的概念。
注意!JS 没有 clss 这个概念,适用于 ES6 之前。
ES6 之后,也引入了 class 关键字,可以让定义对象,就更接近与 Java 了。
但是!这种方式,仍然没有第一种方式来的简单。
而且,第一种创建对象的方式,火了。
不仅仅 JS 会用,其他各种语言,在各种场景下,都会用到。
从这种写法中,延伸出了 JSON(数据的组织格式)
服务器 和 客户端 之间 进行交互的时候,就会经常使用到 JSON 。
i其实,再我们了解了对象的概念之后。
就可以明确,其实再我们的 JS 里面也有一些现成的对象。
这些现成的对象,就可以帮我们完成一些复杂的工作。
像我们的数组,本质上也可以视为是一个对象。
因此对象拥有的一些特性,其实我们的数组也都是有的。
比如说:
我们可以随时给这个对象,动态增加一些属性。
数组也是可以的。(array[‘字符串’])
还需要说一点,虽然 JS 有对象,但是 JS 算是一个面向对象的编程语言吗?
一般认为,不算!
大家需要明确,不是有了对象,它就是面向对象的。
面向对象,需要有一些相关的特性。
比如,JS中没有 封装,继承,多态,这样的一些面向对象的典型特性。
光有一个对象,其实很难把它和面向对象,画上等号。
封装中的 public,private,protected,通过这些关键字来限制访问权限。
让调用者,不用关注里面的实现细节。
继承也是一样。有了父类,就可以让子类继承父类,简化子类的一个编写。
虽然 JS 中没有原生提供 继承的机制,但是JS有一种 “曲线救国” 的方式“原型”。
基于这种原型的机制,它可以模拟实现一个类似于继承的效果。
把一个对象的所有属性,给自动加入到一个新的对象中。
但是!这种模拟实现的过程,并不优雅。
这就不像 Java 直接来个 extends,就没有那么细节让我们去考虑。
JS 直接在语法上,就不支持这个。
多态也差不多,这就不说。
讲到这里,就差不多把 JS 中的 重要的基础语法,带着大家过了一遍。
JS 如果进一步展开,还包含了很多很多其他的语法细节。
因为博主是后端方向,前端不是主要母的。
只是学习前端的一些基础知识,扫个盲而已。
不耽误,我们后面去写一些项目之类的东西。
==========================================================================
学习了上述 JS 语法,能做什么?
感觉除了 会写了个 hello world,就啥也做不了。
要想写实际的程序,光会语言是不够的,还需要掌握相关的“生态”。
生态:配套的库/'框架。
对于 在 浏览器上运行的 JS 来说,最核心的库,就是 DOM API。
DOM API 是浏览器给 JS 提供的原生接口。
基于这样的接口,就可以针对页面上的元素进行操作了。
具体 DOM API 是什么?
DOM =》Document 0bject Model - 文档对象模型
文档:每一个 HTML 就是一个文档
对象:JS 里面的对象。
合在一起,文档对象:在HTML中,会把每个 html 标签,都视为是一个 JS 中可以操作的对象。通过操作这个对象就可以影响到界面的显示。
这个就是文档对象模型。
文档指的是页面显示的部分。对象指的是 JS中代码操作的部分。
JS 这边操作 对象,文档那边就会发生改变。
所以 这两个的关系,是一个相辅相成的关系。
于是,我们就可以通过这样的一组 API,阿里完一些功能更加丰富的页面了。
以上 j就是 DOM 的含义。
JS 中 原生的 DOM API 能用,但是并不方便。
因此除了 原生的 API之外,也就存在了大量的第三方库/框架。
其中 JQuery 就是最知名的一个库。
不过本文,主要还是以 原生的 DOM API 为主。
Vue,React等前端框架,本质上还是 DOM 的封装。
不管你用的什么复合框架,终究是离不开 DOM 这一层东西的。
其实 浏览器,给JS提供的API非常丰富,也有很多组。
前面讲到过的两个
DOM API
BOM API
除此之外,还有一些其它的
WebSocket API,canvas API…
这些 API 统称为 WebAPI。
这里就不做深究,知道 浏览器提供的 API 不止 DOM 和 BOM 就可以了。
另外这里,分享一个资源 API参考文档
另外,也可以在搜索引擎中按照 “MDN + API 关键字” 的方式搜索, 也能快速找到需要的 API 文档
DOM 全称为 Document Object Model.
W3C 标准给我们提供了一系列的函数, 让我们可以操作:
网页内容
网页结构
网页样式
一个页面的结构是一个树形结构, 称为 DOM 树
页面结构形如:
DOM 树结构形如
重要概念:
文档: 一个页面就是一个 文档, 使用 document 表示.
元素: 页面中所有的标签都称为 元素. 使用 element 表示.
节点: 网页中所有的内容都可以称为 节点(标签节点, 注释节点, 文本节点, 属性节点等). 使用 node表示.
这些文档等概念在 JS 代码中就对应一个个的对象.
所以才叫 “文档对象模型” .
换取元素,是使用 DOM 的基础。
要想使用操作页面上的元素,就需要先拿到对应的JS 对象。
获取 JS 对象的过程,就是获取元素的过程。
怎么去获取元素呢?
其实 JS 中提供好几种方法来获取元素。
其中,本文主要就介绍两种最核心的方法。
1、querySelector
2、querySelectorAll
这两个函数,其实是一个 document 这样的对象的属性。
document:是属于 页面中的 一个 全局对象。
页面中的全局对象
一个页面加载好了,就会自动生成一个全局变量,就叫做 document。
这里面就有一些属性和方法,让我们来操作页面的内容。
document的中文意思就是文档的意思,所以我们当前所看到的 document 对象,就是我们页面文档,在JS中的一个“身外化身”。
下面,我们就来具体的写一下代码,演示一下关于 querySelector / querySelectorAll,获取元素的基础操作。
以上就是 querySelector / querySelectorAll,两种主流 获取 DOM 元素的 原生API。
当然了,像我们后续的 jquery 和 vue 的一些框架里面,有一些更加方便的方式来获取 DOM 对象。这些方法也是基于 DOM 的 原生 API。
大家只要把 DOM 原生的 API学习,后面即使我们遇到更加 复杂的 / 强大的 一些方法,也是能理解的。
最后
面试一面会问很多基础问题,而这些基础问题基本上在网上搜索,面试题都会很多很多。最好把准备一下常见的面试问题,毕竟面试也相当与一次考试,所以找工作面试的准备千万别偷懒。面试就跟考试一样的,时间长了不复习,现场表现肯定不会太好。表现的不好面试官不可能说,我猜他没发挥好,我录用他吧。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
96道前端面试题:
常用算法面试题:
前端基础面试题:
内容主要包括HTML,CSS,JavaScript,浏览器,性能优化
MDN + API 关键字” 的方式搜索, 也能快速找到需要的 API 文档
DOM 全称为 Document Object Model.
W3C 标准给我们提供了一系列的函数, 让我们可以操作:
网页内容
网页结构
网页样式
一个页面的结构是一个树形结构, 称为 DOM 树
页面结构形如:
DOM 树结构形如
重要概念:
文档: 一个页面就是一个 文档, 使用 document 表示.
元素: 页面中所有的标签都称为 元素. 使用 element 表示.
节点: 网页中所有的内容都可以称为 节点(标签节点, 注释节点, 文本节点, 属性节点等). 使用 node表示.
这些文档等概念在 JS 代码中就对应一个个的对象.
所以才叫 “文档对象模型” .
换取元素,是使用 DOM 的基础。
要想使用操作页面上的元素,就需要先拿到对应的JS 对象。
获取 JS 对象的过程,就是获取元素的过程。
怎么去获取元素呢?
其实 JS 中提供好几种方法来获取元素。
其中,本文主要就介绍两种最核心的方法。
1、querySelector
2、querySelectorAll
这两个函数,其实是一个 document 这样的对象的属性。
document:是属于 页面中的 一个 全局对象。
页面中的全局对象
一个页面加载好了,就会自动生成一个全局变量,就叫做 document。
这里面就有一些属性和方法,让我们来操作页面的内容。
document的中文意思就是文档的意思,所以我们当前所看到的 document 对象,就是我们页面文档,在JS中的一个“身外化身”。
下面,我们就来具体的写一下代码,演示一下关于 querySelector / querySelectorAll,获取元素的基础操作。
以上就是 querySelector / querySelectorAll,两种主流 获取 DOM 元素的 原生API。
当然了,像我们后续的 jquery 和 vue 的一些框架里面,有一些更加方便的方式来获取 DOM 对象。这些方法也是基于 DOM 的 原生 API。
大家只要把 DOM 原生的 API学习,后面即使我们遇到更加 复杂的 / 强大的 一些方法,也是能理解的。
最后
面试一面会问很多基础问题,而这些基础问题基本上在网上搜索,面试题都会很多很多。最好把准备一下常见的面试问题,毕竟面试也相当与一次考试,所以找工作面试的准备千万别偷懒。面试就跟考试一样的,时间长了不复习,现场表现肯定不会太好。表现的不好面试官不可能说,我猜他没发挥好,我录用他吧。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
96道前端面试题:
- [外链图片转存中…(img-21yZyQpo-1714561178699)]
常用算法面试题:
- [外链图片转存中…(img-gld3dDfe-1714561178700)]
前端基础面试题:
内容主要包括HTML,CSS,JavaScript,浏览器,性能优化