前端三剑客 HTML、CSS、JavaScript 入门到上手

一. HTML基础使用

HTML:超文本标记语言,是一种用于创建网页的标准标记语言。

HTML 代码是由 “标签” 构成的整体的 HTML 代码是由一对 <html> </html> 包裹的<head> </head> 标签是页面的头部,标签中写页面的属性<body> </body> 标签是页面的主体,标签中写的是页面显示的内容<title> </title> 标签中写的是页面的标题

1.HTML 入门实例

<html> <head> <title>第⼀个⻚⾯</title> </head> <body> hello world </body> </html>

这三个标签组成了一个html的主体,也是一个最简单的页面。每个标签,都分成了开始标签和结束标签,是成对出现的,标签之间可以嵌套。

整体这些标签就构成了一个 树形 结构,称为 DOM 树(DOM Document Objective Model 文档对象模型)

生成一个默认的页面模板: 输入 !, 并且按 tab,就可以生成一组默认的页面模板。

解释一下这个模板:

<!DOCTYPE html> : 这一行是声明了文档类型,描述了当前文件是 html 文件

<html lang=”en”> : 表示当前网页使用的语言是 english。→ 这里标记了语言也是方便了浏览器自带的翻译功能进行识别。

<head>标签里面放的内容主要是页面的一些属性,和页面展示的内容没有太大关系。<meta charset=”UTF-8″>声明我们这个页面的字符编码是 UTF-8,<tatle> 里面包裹的是浏览器标签页的默认标题。

<body>里面就是页面要展示的内容。

下面就要开始介绍 HTML 具体的语法细节了,值得一提的是,前端这里涉及的 HTML、CSS、JS 这三门语言,但是实际上,只有 JS 是一个可编程的语言,其他两个都只是作用了页面显示的“信息”,语法规则中不表达“逻辑”,只是表示信息。下面介绍的就是组成一个页面上的元素,也就是 HTML 语言的主体——标签。

2 HTML 常见标签

① 注释标签

ctrl + / 快捷键可以快速注释/取消注释。
<!– 我是注释 –>

注释不会显示在界面上,目的是提高代码的可读性。

② 标题标签

标题标签有6个:<h1>…<h6> 数字越大,字体越小

③ 段落标签

段落标签是用 <p> 来定义的

段落标签保证了每一个段落是存在在一行的,并且距离下一个段落中间会空有一行的间距。下面我们用lorem生成一个随机的比较长的字符串再来测试一下我们的<p>标签的展示效果:

这样我们就比较清楚的看到每一个段落之间的效果了。

④ 换行标签

段落标签是用 <br> 来定义的

和<p>不一样的是,<br>他只会进行换行,不会分段使每段之间有一个空行,且 br 标签是一个“单标签”,只有开始标签,没有结束标签。

HTML转义字符

heml 语法里的有些特殊字符需要转义才能够正确的显示,我们需要了解,比如空格,不是我们在代码里输出几个空格页面就会正确的显示多个空格的,html 会把相邻的空格合并成一个空格。而我们需要使用转义字符 &nbsp; ,需要多少空格输入多少次 &nbsp; 才能正确的显示出来自己需要的样式。 HTML转义字符

⑤ 格式化标签

加粗:strong 标签 和 b 标签倾斜:em 标签 和 i 标签删除线:del 标签 和 s 标签下划线:ins 标签 和 u 标签

格式化标签是作用在文本上的,所以不难理解,格式化标签不会像之前的块级元素例如标题标签一样的会独占一行,而是作为行内元素直接作用在被标签包裹的文本上的。

⑥ 图片标签

图片标签是用<img>来表示的,img 中的 src 属性,就代表了图片的路径,同样图片的样式和名称也是由属性来决定的。

如果我们还想设置图片的尺寸:

从图片标签里我们接触到了标签的 “属性” ,是的,在 html 的开始标签里,可以给标签设置一些属性。且属性是用 “ 键值对 ” 这样的形式表示的。

键值对之间使用空格来分割;键值对之间使用 = 来分割;key不需要 ” ” ,value 内容用 ” ” 包裹起来。

⑦ 超链接标签

超链接标签用<a> </a>来表示,其中的href属性表示点击后会跳转到哪个页面,target表示打开方式,默认是_self,在本标签页打开,如果设置为_blank,则用新的标签页打开。

外部链接

<a href=”https://www.baidu.com”>这是超链接,点击跳转到百度</a

内部链接

<a href=”htmlDemo1.html”>跳转到自己文件夹中的另外一个html网页</a>

空链接

<a href=”#”>这是一个空连接</a>

下载链接

<a href = “cat.zip”>点击下载这个压缩包 </a>

锚点链接

类似于目录,点击之后会跳转到本页面中的特定的位置。

⑧ 表格标签

table 标签: 表示整个表格tr: 表示表格的一行td: 表示一个单元格th: 表示表头单元格. 会居中加粗thead: 表格的头部区域(注意和 th 区分, 范围是比 th 要大的)tbody: 表格得到主体区域.

⑨ 列表标签

⑩ 表单标签

表单标签是用户和页面交互的重要手段,是要让用户来“输入”的。

form 标签

用<form> </form>来创建一个表单标签,借助 form 就可以允许用户输入一些信息,并且提交到 服务器 上。

input 标签

type(必须有), 取值种类很多多, button, checkbox, text, file, image, password, radio 等.name: 给 input 起了个名字. 尤其是对于 单选按钮, 具有相同的 name 才能多选一.value: input 中的默认值.checked: 默认被选中. (用于单选按钮和多选按钮)maxlength: 设定最大长度.

onclick

onclick表示在点击元素的时候触发,触发的内容就是 ” ” 里的代码, 会被浏览器直接执行。这里的alert就是弹出一个对话框。

上面页面效果也可以使用代码

<button onclick=”alert(hello HTML)”>这是一个按钮</button>

来实现。

label 标签

每一个 html 元素(标签),都可以设置一个唯一的 id,在一个页面中,id 的取值不能重复。

通过这个 id 属性,在 input 标签设置选中框操作上搭配 label 标签,实现通过点击文字,也能选中的效果。

select 标签

可以实现一个下拉菜单

textarea 标签

是一个可以指定多行编辑框的标签

⑪ 无语义标签

div 默认是一个块级元素(独占一行)

span 默认是一个行内元素(不独占一行)

前面的标签,都是 “有语义” 的标签,每个标签都有一个明确的 “角色”;

但是相对于我们现在使用 HTML 语言显示一个页面,页面的内容相对来说比较复杂,交互效果比较丰富。也就是对“功能”的概念相对弱化,而更多的是体现出“展示效果”。

二. CSS 层叠样式表

前面的 HTML 只是表示页面的结构和内容~ CSS 描述的是页面的样式(具体来说,就是描述了一个网页的元素),让一个页面变得好看起来。

每一个 CSS 语句包含两个部分:选择器 + 应用的属性

1 .CSS 的引入方式:

1.1 行内样式

在某个标签中,引入 style 属性,来指定样式

1.2 内联样式

写在 style 标签中,嵌入到 html 内部的样式

内联样式只适合于特别简单的情况,如果样式比较复杂,不建议用这种写法

1.3 外部样式

把 CSS 代码单独提取出来,放到一个 .css 文件中,然后在 html 代码里,通过 link 标签,来引入该 CSS 文件。

2 选择器

选择器的功能就是选中页面的元素(标签)

2.1 基础选择器

标签选择器用 html 的一个标签名写的选择器类选择器在 CSS 代码中创建一个类名,此时具有该类名的元素,都会应用上相关的 CSS 属性
id 选择器给被选中的元素(标签),设置个 id 属性
通配符选择器直接选中页面上的所有元素,一般最大的用途是 取消浏览器的默认样式

经典写法:

2.2 复合选择器

后代选择器实现选择器能够选中 某个元素 里面的后代元素的方法,用多个选择器组合使用
子选择器一种选择器嵌套另外一种选择器的方式
并集选择器并列的写多个选择器

3 常用元素属性

CSS语法文档 – MDN

3.1 字体属性

① 字体样式

body { font-family: 微软雅⿊; font-family: Microsoft YaHei; }

② 字体大小

p { font-size: 20px; }

③ 字体粗细

p { font-weight: bold; font-weight: 700; }

④ 文字样式

/* 设置倾斜 */ font-style: italic; /* 取消倾斜 */ font-style: normal;

3.2 文本属性

① 文本的颜色

我们的显示器是由很多很多的 “像素” 构成的. 每个像素视为⼀个点, 这个点就能反映出⼀个具体的颜⾊. 我们使用 R (red), G (green), B (blue) 的⽅式表示颜色(色光三原⾊). 三种颜⾊按照不同的比例搭配, 就能混合出各种五彩斑斓的效果.

color: red; color: #ff0000; color: rgb(255, 0, 0);

在 rgb 中通过不同的分量拉不同的值,就能得到不同的颜色。

rgba :透明度。

② 文本对齐

center: 居中对齐left: 左对齐right: 右对齐

③ 文本装饰

underline 下划线. [常用]none 啥都没有. 可以给 a 标签去掉下划线.overline 上划线. [不常用]line-through 删除线 [不常用]

④ 文本对齐

text-indent: [值];
单位可以使用 px 或者 em.使用 em 作为单位更好. 1 个 em 就是当前元素的文字大小.缩进可以是负的, 表示往左缩进. (会导致文字就冒出去了)

3.3 背景属性

① 背景颜色

background-color: [指定颜⾊]

② 背景图片

background-image: url(…);

③ 背景平铺

background-repeat: [平铺⽅式]
repeat: 平铺no-repeat: 不平铺repeat-x: ⽔平平铺repeat-y: 垂直平铺

④ 背景尺寸

background-size: length|percentage|cover|contain;

三. JS 基础语法

JavaScript (简称 JS)

是世界上最流行的编程语言之一是一个脚本语言, 通过解释器运行主要在客户端(浏览器)上运行, 现在也可以基于 node.js 在服务器端运行.

1.JavaScript 和 HTML 和 CSS 之间的关系

2.JavaScript 的书写形式

1. 行内式

直接嵌入到 html 元素内部

<input type=”button” value=”点我一下” onclick=”alert(haha)”>

注意, JS 中字符串常量可以使用单引号表示, 也可以 使用双引号表示.

HTML 中推荐使用双引号, JS 中推荐使用单引号.

2. 内嵌式

写到 script 标签中

<script> alert(“haha”); </script>

3. 外部式

写到单独的 .js 文件中

<script src=”hello.js”></script>
alert(“hehe”);

注意, 这种情况下 script 标签中间不能写代码. 必须空着(写了代码也不会执行).

适合代码多的情况.

3.变量的使用

基本用法

创建变量(变量定义/变量声明/变量初始化)

var name = zhangsan; var age = 20;

var 是 JS 中的关键字, 表示这是一个变量.

= 在 JS 中表示 “赋值”, 相当于把数据放到内存的盒子中. = 两侧建议有一个空格

每个语句最后带有一个 ; 结尾. JS 中可以省略 ; 但是建议还是加上.

注意, 此处的 ; 为英文分号. JS 中所有的标点都是英文标点.

初始化的值如果是字符串, 那么就要使用单引号或者双引号引起来.

初始化的值如果是数字, 那么直接赋值即可.

使用变量

console.log(age); // 读取变量内容 age = 30; // 修改变量内容

为啥动漫中的角色都是要先喊出技能名字再真正释放技能?

就是因为变量要先声明才能使用.

代码示例: 弹框提示用户输入信息, 再弹框显示.

var name = prompt(“请输入姓名:”); var age = prompt(“请输入年龄:”); var score = prompt(“请输入分数”); alert(“您的姓名是: ” + name); alert(“您的年龄是: ” + age); alert(“您的分数是: ” + score);

也可以把三个输出内容合并成一次弹框

var name = prompt(“请输入姓名:”); var age = prompt(“请输入年龄:”); var score = prompt(“请输入分数”); alert(“您的姓名是: ” + name + “\n” + “您的年龄是: ” + age + “\n” + “您的分数是: ” + score + “\n”);
+ 表示字符串拼接, 也就是把两个字符串首尾相接变成一个字符串.\n 表示换行JavaScript 中还支持使用 let 定义变量. 用法和 var 基本类似. 用法上的差异此处暂时不讨论.

理解 动态类型

JS 的变量类型是程序运行过程中才确定的(运行到 = 语句才会确定类型)

var a = 10; // 数字 var b = “hehe”; // 字符串

随着程序运行, 变量的类型可能会发生改变.

var a = 10; // 数字 a = “hehe”; // 字符串

这一点和 C Java 这种静态类型语言差异较大.

C, C++, Java, Go 等语言是静态类型语言. 一个变量在创建的时候类型就确定了, 不能在运行时发生改变.

如果尝试改变, 就会直接编译报错.

4.基本数据类型

JS 中内置的几种类型

number: 数字. 不区分整数和小数.boolean: true 真, false 假.string: 字符串类型.undefined: 只有唯一的值 undefined. 表示未定义的值.null: 只有唯一的值 null. 表示空值.

number 数字类型

JS 中不区分整数和浮点数, 统一都使用 “数字类型” 来表示.

数字进制表示

计算机中都是使用二进制来表示数据, 而人平时都是使用十进制.

因为二进制在使用过程中不太方便(01太多会看花眼).

所以在日常使用二进制数字时往往使用 八进制 和 十六进制 来表示二进制数字.

var a = 07; // 八进制整数, 以 0 开头 var b = 0xa; // 十六进制整数, 以 0x 开头 var c = 0b10; // 二进制整数, 以 0b 开头

注意:

一个八进制数字对应三个二进制数字一个十六进制数字对应四个二进制数字. (两个十六进制数字就是一个字节)各种进制之间的转换, 不需要手工计算, 直接使用计算器即可.

特殊的数字值

Infinity: 无穷大, 大于任何数字. 表示数字已经超过了 JS 能表示的范围.-Infinity: 负无穷大, 小于任何数字. 表示数字已经超过了 JS 能表示的范围.NaN: 表示当前的结果不是一个数字.
var max = Number.MAX_VALUE; // 得到 Infinity console.log(max * 2); // 得到 -Infinity console.log(-max * 2); // 得到 NaN console.log(hehe – 10);

注意:

负无穷大 和 无穷小 不是一回事. 无穷小指无限趋近与 0, 值为 1 / Infinity‘hehe’ + 10 得到的不是 NaN, 而是 ‘hehe10’, 会把数字隐式转成字符串, 再进行字符串拼接.可以使用 isNaN 函数判定是不是一个非数字.
console.log(isNaN(10)); // false console.log(isNaN(hehe – 10)); // true

string 字符串类型

基本规则

字符串字面值需要使用引号引起来, 单引号双引号均可.

var a = “haha”; var b = hehe; var c = hehe; // 运行出错

如果字符串中本来已经包含引号咋办?

var msg = “My name is “zhangsan””; // 出错 var msg = “My name is \”zhangsan\””; // 正确, 使用转义字符. \” 来表示字符串内部的引号. var msg = “My name is zhangsan”; // 正确, 搭配使用单双引号 var msg = My name is “zhangsan”; // 正确, 搭配使用单双引号

转义字符

有些字符不方便直接输入, 于是要通过一些特殊方式来表示.

\n\\\\” \t

求长度

使用 String 的 length 属性即可

var a = hehe; console.log(a.length); var b = 哈哈; console.log(b.length);

结果:

4 2

单位为字符的数量

字符串拼接

使用 + 进行拼接

var a = “my name is “; var b = “zhangsan”; console.log(a + b);

注意, 数字和字符串也可以进行拼接

var c = “my score is “; var d = 100; console.log(c + d);

注意, 要认准相加的变量到底是字符串还是数字

console.log(100 + 100); // 200 console.log(100 + 100); // 100100

boolean 布尔类型

表示 “真” 和 “假”

boolean 原本是数学中的概念 (布尔代数).

在计算机中 boolean 意义重大, 往往要搭配条件/循环完成逻辑判断.

Boolean 参与运算时当做 1 和 0 来看待.

console.log(true + 1); console.log(false + 1)

这样的操作其实是不科学的. 实际开发中不应该这么写.

undefined 未定义数据类型

如果一个变量没有被初始化过, 结果就是 undefined, 是 undefined 类型

var a; console.log(a)

undefined 和字符串进行相加, 结果进行字符串拼接

console.log(a + “10”); // undefined10

undefined 和数字进行相加, 结果为 NaN

console.log(a + 10);

null 空值类型

null 表示当前的变量是一个 “空值”.

var b = null; console.log(b + 10); // 10 console.log(b + “10”); // null10

注意:

null 和 undefined 都表示取值非法的情况, 但是侧重点不同.

null 表示当前的值为空. (相当于有一个空的盒子)

undefined 表示当前的变量未定义. (相当于连盒子都没有)

5.运算符

JavaScript 中的运算符和 Java 用法基本相同. 此处不做详细介绍了.

算术运算符

+-*/%

赋值运算符 & 复合赋值运算符

=+=-=*=/=%=自增自减运算符++: 自增1–: 自减1

比较运算符

<><=>=== 比较相等(会进行隐式类型转换)!==== 比较相等(不会进行隐式类型转换)!==

逻辑运算符

用于计算多个 boolean 表达式的值.

&& 与: 一假则假|| 或: 一真则真! 非

位运算

& 按位与| 按位或~ 按位取反^ 按位异或

移位运算

<< 左移>> 有符号右移(算术右移)>>> 无符号右移(逻辑右移)

6.条件语句

if 语句

基本语法格式

条件表达式为 true, 则执行 if 的 { } 中的代码

// 形式1 if (条件) { 语句 } // 形式2 if (条件) { 语句1 } else { 语句2 } // 形式3 if (条件1) { 语句1 } else if (条件2) { 语句2 } else if …. { 语句… } else { 语句N }

三元表达式

是 if else 的简化写法.

条件 ? 表达式1 : 表达式2

条件为真, 返回表达式1 的值. 条件为假, 返回表达式2 的值.

注意, 三元表达式的优先级是比较低的.

switch

更适合多分支的场景.

switch (表达式) { case 值1: 语句1; break; case 值2: 语句2: break; default: 语句N; }

用户输入一个整数, 提示今天是星期几

var day = prompt(“请输入今天星期几: “); switch (parseInt(day)) { case 1: console.log(“星期一”); break; case 2: console.log(“星期二”); break; case 3: console.log(“星期三”); break; case 4: console.log(“星期四”); break; case 5: console.log(“星期五”); break; case 6: console.log(“星期六”); break; case 7: console.log(“星期日”); break; default: console.log(“输入有误”); }

7.循环语句

重复执行某些语句

while 循环

while (条件) { 循环体; }

执行过程:

先执行条件语句条件为 true, 执行循环体代码.条件为 false, 直接结束循环

代码示例1: 打印 1 – 10

var num = 1; while (num <= 10) { console.log(num); num++; }

代码示例2:计算 5 的阶乘

var result = 1; var i = 1; while (i <= 5) { result *= i; i++; } console.log(result)

continue

结束这次循环

吃五个李子, 发现第三个李子里有一只虫子, 于是扔掉这个, 继续吃下一个李子.

var i = 1; while (i <= 5) { if (i == 3) { i++; continue; } console.log(“我在吃第” + i + “个李子”); i++; }
我在吃第1个李子 我在吃第2个李子 我在吃第4个李子 我在吃第5个李子

代码示例:找到 100 – 200 中所有 3 的倍数

var num = 100; while (num <= 200) { if (num % 3 != 0) { num++; // 这里的 ++ 不要忘记! 否则会死循环. continue; } console.log(“找到了 3 的倍数, 为:” + num); num++; }

break

结束整个循环

吃五个李子, 发现第三个李子里有半个虫子, 于是剩下的也不吃了.

var i = 1; while (i <= 5) { if (i == 3) { break; } console.log(“我在吃第” + i + “个李子”); i++; }
我在吃第1个李子 我在吃第2个李子

代码示例: 找到 100 – 200 中第一个 3 的倍数

var num = 100; while (num <= 200) { if (num % 3 == 0) { console.log(“找到了 3 的倍数, 为:” + num); break; } num++; } // 执行结果 找到了 3 的倍数, 为:102

for 循环

for (表达式1; 表达式2; 表达式3) { 循环体 }
表达式1: 用于初始化循环变量.表达式2: 循环条件表达式3: 更新循环变量.

执行过程:

先执行表达式1, 初始化循环变量再执行表达式2, 判定循环条件如果条件为 false, 结束循环如果条件为 true, 则执行循环体代码.执行表达式3 更新循环变量

代码示例1: 打印 1 – 10 的数字

for (var num = 1; num <= 10; num++) { console.log(num); }

**代码示例2:**计算 5 的阶乘

var result = 0; for (var i = 1; i <= 5; i++) { result *= i; } console.log(“result = ” + result);

8.数组

创建数组

使用 new 关键字创建

// Array 的 A 要大写 var arr = new Array();

使用字面量方式创建 [常用]

var arr = []; var arr2 = [1, 2, haha, false]; // 数组中保存的内容称为 “元素”

注意: JS 的数组不要求元素是相同类型.

这一点和 C, C++, Java 等静态类型的语言差别很大. 但是 Python, PHP 等动态类型语言也是如此.

获取数组元素

使用下标的方式访问数组元素(从 0 开始)

var arr = [小猪佩奇, 小猪乔治, 小羊苏西]; console.log(arr); console.log(arr[0]); console.log(arr[1]); console.log(arr[2]); arr[2] = 小猫凯迪; console.log(arr);

如果下标超出范围读取元素, 则结果为 undefined

console.log(arr[3]); // undefined console.log(arr[-1]); // undefined

注意: 不要给数组名直接赋值, 此时数组中的所有元素都没了.

相当于本来 arr 是一个数组, 重新赋值后变成字符串了.
var arr = [小猪佩奇, 小猪乔治, 小羊苏西]; arr = 小猫凯迪;

新增数组元素

1. 通过修改 length 新增

相当于在末尾新增元素. 新增的元素默认值为 undefined

var arr = [9, 5, 2, 7]; arr.length = 6; console.log(arr); console.log(arr[4], arr[5]);

2. 通过下标新增

如果下标超出范围赋值元素, 则会给指定位置插入新元素

var arr = []; arr[2] = 10; console.log(arr)

此时这个数组的 [0] 和 [1] 都是 undefined

3. 使用 push 进行追加元素

代码示例: 给定一个数组, 把数组中的奇数放到一个 newArr 中.

var arr = [9, 5, 2, 7, 3, 6, 8]; var newArr = []; for (var i = 0; i < arr.length; i++) { if (arr[i] % 2 != 0) { newArr.push(arr[i]); } } console.log(newArr);

删除数组中的元素

使用 splice 方法删除元素

var arr = [9, 5, 2, 7]; // 第一个参数表示从下表为 2 的位置开始删除. 第二个参数表示要删除的元素个数是 1 个 arr.splice(2, 1); console.log(arr); // 结果 [9, 5, 7]

arr.length, length 使用的时候不带括号, 此时 length 就是一个普通的变量(称为成员变量, 也叫属性)

arr.push(), arr.splice() 使用的时候带括号, 并且可以传参数, 此时是一个函数 (也叫做方法)

9.函数

语法格式

// 创建函数/函数声明/函数定义 function 函数名(形参列表) { 函数体 return 返回值; } // 函数调用 函数名(实参列表) // 不考虑返回值 返回值 = 函数名(实参列表) // 考虑返回值
函数定义并不会执行函数体内容, 必须要调用才会执行. 调用几次就会执行几次.
function hello() { console.log(“hello”); } // 如果不调用函数, 则没有执行打印语句 hello();
调用函数的时候进入函数内部执行, 函数结束时回到调用位置继续执行. 可以借助调试器来观察.函数的定义和调用的先后顺序没有要求. (这一点和变量不同, 变量必须先定义再使用)
// 调用函数 hello(); // 定义函数 function hello() { console.log(“hello”); }

关于参数个数

实参和形参之间的个数可以不匹配. 但是实际开发一般要求形参和实参个数要匹配

如果实参个数比形参个数多, 则多出的参数不参与函数运算
sum(10, 20, 30); // 30

2.如果实参个数比形参个数少, 则此时多出来的形参值为 undefined

sum(10); // NaN, 相当于 num2 为 undefined.

JS 的函数传参比较灵活, 这一点和其他语言差别较大. 事实上这种灵活性往往不是好事.

函数表达式

另外一种函数的定义方式

var add = function() { var sum = 0; for (var i = 0; i < arguments.length; i++) { sum += arguments[i]; } return sum; } console.log(add(10, 20)); // 30 console.log(add(1, 2, 3, 4)); // 10 console.log(typeof add); // function

此时形如 function() { } 这样的写法定义了一个匿名函数, 然后将这个匿名函数用一个变量来表示.

后面就可以通过这个 add 变量来调用函数了.

JS 中函数是一等公民, 可以用变量保存, 也可以作为其他函数的参数或者返回值.

作用域

某个标识符名字在代码中的有效范围.

在 ES6 标准之前, 作用域主要分成两个

全局作用域: 在整个 script 标签中, 或者单独的 js 文件中生效.局部作用域/函数作用域: 在函数内部生效.
// 全局变量 var num = 10; console.log(num); function test() { // 局部变量 var num = 20; console.log(num); } function test2() { // 局部变量 var num = 30; console.log(num); } test(); test2(); console.log(num); // 执行结果 10 20 30 10

创建变量时如果不写 var, 则得到一个全局变量.

function test() { num = 100; } test(); console.log(num); // 执行结果 100

另外, 很多语言的局部变量作用域是按照代码块(大括号)来划分的, JS 在 ES6 之前不是这样的.

if (1 < 2) { var a = 10; } console.log(a);

作用域链

背景:

函数可以定义在函数内部内层函数可以访问外层函数的局部变量.

内部函数可以访问外部函数的变量. 采取的是链式查找的方式. 从内到外依次进行查找.

var num = 1; function test1() { var num = 10; function test2() { var num = 20; console.log(num); } test2(); } test1(); // 执行结果 20

执行 console.log(num) 的时候, 会现在 test2 的局部作用域中查找 num. 如果没找到, 则继续去 test1 中查找. 如果还没找到, 就去全局作用域查找.

JavaScript 的对象和 Java 的对象的区别

1. JavaScript 没有 “类” 的概念

对象其实就是 “属性” + “方法” .

类相当于把一些具有共性的对象的属性和方法单独提取了出来, 相当于一个 “月饼模子”

在 JavaScript 中的 “构造函数” 也能起到类似的效果.

而且即使不是用构造函数, 也可以随时的通过 { } 的方式指定出一些对象

在 ES6 中也引入了 class 关键字, 就能按照类似于 Java 的方式创建类和对象了.

2. JavaScript 对象不区分 “属性” 和 “方法”

JavaScript 中的函数是 “一等公民”, 和普通的变量一样. 存储了函数的变量能够通过 ( ) 来进行调用执行.

3. JavaScript 对象没有 private / public 等访问控制机制.

对象中的属性都可以被外界随意访问.

4. JavaScript 对象没有 “继承”

继承本质就是 “让两个对象建立关联”. 或者说是让一个对象能够重用另一个对象的属性/方法.

JavaScript 中使用 “原型” 机制实现类似的效果.

例如: 创建一个 cat 对象和 dog 对象, 让这两个对象都能使用 animal 对象中的 eat 方法.

通过 __proto__ 属性来建立这种关联关系 (proto 翻译作 “原型”)

当eat方法被调用的时候,先在自己的方法列表中寻找, 如果找不到,就去找原型中的方法, 如果原型中找不到, 就去原型的原型中去寻找… 最后找到Object那里, 如果还找不到, 那就是未定义了。

关于原型链的内容比较复杂, 此处不做过多讨论。

5. JavaScript 没有 “多态”

多态的本质在于 “程序猿不必关注具体的类型, 就能使用其中的某个方法”.

C++ / Java 等静态类型的语言对于类型的约束和校验比较严格. 因此通过 子类继承父类, 并重写父类的方法的方式 来实现多态的效果.

但是在 JavaScript 中本身就支持动态类型, 程序猿在使用对象的某个方法的时候本身也不需要对对象的类型做出明确区分. 因此并不需要在语法层面上支持多态.

例如:

在 Java 中已经学过 ArrayList 和 LinkedList. 为了让程序猿使用方便, 往往写作

List<String> list = new ArrayList<>()

然后我们可以写一个方法:

void add(List<String> list, String s) { list.add(s); }

我们不必关注 list 是 ArrayList 还是 LinkedList, 只要是 List 就行. 因为 List 内部带有 add 方法.

当我们使用 JavaScript 的代码的时候

function add(list, s) { list.add(s) }

add 对于 list 这个参数的类型本身就没有任何限制. 只需要 list 这个对象有 add 方法即可. 就不必像 Java 那样先继承再重写绕一个圈子.

JavaScript 进阶

原出处:CSDN

原作者:阿布~

原文链接:https://blog.csdn.net/weixin_46448719/article/details/124383884

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧