本篇文章为大家带来JavaScript的学习,一图胜千言~~~
目录
3.2 JavaScript 对象不区分 "属性" 和 "方法"
3.3 JavaScript 对象没有 private / public 等访问控制机制
一、JavaScript是什么
1.1 JavaScript (简称 JS)
- 是世界上最流行的编程语言之一
- 是一个脚本语言, 通过解释器运行
- 主要在客户端(浏览器)上运行, 现在也可以基于 node.js 在服务器端运行
JavaScript 最初只是为了完成简单的表单验证(验证数据合法性), 结果后来不小心就火了.
当前 JavaScript 已经成为了一个通用的编程语言
JavaScript 的能做的事情:
- 网页开发(更复杂的特效和用户交互)
- 网页游戏开发
- 服务器开发(node.js)
- 桌面程序开发(Electron, VSCode 就是这么来的)
- 手机 app 开发
1.2 JavaScript发展历史
JavaScript 之父 布兰登 * 艾奇 (Brendan Eich)
曾经的布兰登
发明 JavaScript 之后的布兰登
他在1995年, 用10天时间完成JS的设计, 最初在网景公司(Netscape), 命名为 LiveScript, 一般认为, 当时 Netscape之所以将LiveScript命名为JavaScript, 是因为Java是当时最流行的编程语言, 带有 “Java” 的名字有助于这门新生语言的传播, 但实际上Java和JavaScript之间的语法风格相差甚远, 基本是没有关系的.
JS主要在前端中可以完成用户在网页和Web服务器的交互, HTML描述了网页的结构(骨), CSS描述了网页的样式(皮), JavaScript则描述了网页的行为(魂).
1.3 JavaScript运行过程
编写的代码是保存在文件中的, 也就是存储在硬盘(外存上).
双击 .html 文件浏览器(应用程序)就会读取文件, 把文件内容加载到内存中(数据流向: 硬盘 => 内存)
浏览器会解析用户编写的代码, 把代码翻译成二进制的, 能让计算机识别的指令(解释器的工作)
得到的二进制指令会被 CPU 加载并执行(数据流向: 内存 => CPU)
浏览器分成渲染引擎 + JS 引擎.
- 渲染引擎: 解析 html + CSS, 俗称 "内核"
- JS 引擎: 也就是 JS 解释器. 典型的就是 Chrome 中内置的 V8
二、JavaScript的基础语法
2.1 JavaScript的组成
-
ECMAScript(简称 ES): JavaScript 语法
-
DOM: 页面文档对象模型, 对页面中的元素进行操作
-
BOM: 浏览器对象模型, 对浏览器窗口进行操作
光有 JS 语法, 只能写一些基础的逻辑流程.
但是要想完成更复杂的任务, 完成和浏览器以及页面的交互, 那么久需要 DOM API 和 BOM API.
注释:
- 单行注释 // [建议使用]
- 多行注释 /* */
// 我是单行注释
/*
我是多行注释
我是多行注释
我是多行注释
*/
多行注释不能嵌套. 形如这种代码就会报错
/*
/*
我是多行注释
我是多行注释
我是多行注释
*/
*/
2.2 第一个程序
<!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>
alert('您好!');
</script>
</body>
</html>
此时,大家可以看到,JS是要作用在HTML上的script标签的,在html文件中存在
2.3 JS的三种写法
1.行内式
<button onclick="alert('hello js')">点击进入第一个js程序</button>
要注意JS中字符串常量可以使用单引号表示, 也可以使用双引号表示
2.内嵌式
<script>
alert("helloJS");
</script>
由于 html的编译是从上到下的,如果js代码获取html中的标签元素的时候,该元素未被初始化,就会出错,那么我们建议将js代码写在最后,body标签结束之前!!!
script标签的位置放前面错误案例:
通过document(本文件对象),再通过id获取标签元素对象,的属性value的值,并将它alert,并且这是在head里,此时就会报错,因为从上到下还没有加载到id为btn1的元素!!
3.外部式
<!-- 外部式 -->
<script src="tools.js"></script>
得到的效果和上面是一样的.
2.4 变量
语法格式:
//第一种定义方式
var 变量名 = 值;
//第二种定义方式
let 变量名 = 值;
与java/c/c++不同的是, 关键字var/let
定义的变量可以接收多种类型的变量值, 可以是整数, 浮点数, 字符串, 数组等.JS代码中每个语句最后带有一个;
结尾, 可以省略, 但是建议还是加上.初始化的值如果是字符串, 那么就要使用单引号或者双引号引起来
var和let的区别:
- var,定义全局变量的
- let,定义局部变量的
let是最新ES6之后新出来的,主要是为了区分局部变量
代码示例1:弹框提示用户输入信息, 再弹框显示
<script>
var name = prompt("请输入姓名:");
var age = prompt("请输入年龄:");
var score = prompt("请输入分数");
alert("您的姓名是: " + name + "\n" + "您的年龄是: " + age + "\n" + "您的分数是: " +
score + "\n");
</script>
alert代表弹出一个警示对话框,输出结果~~
代码示例2:字符串拼接
var numb1 = "10";
var numb2 = "20";
alert(numb1 + numb2);
代码示例3: 字符串+数字
var numb1 = "10";
var numb2 = 20;
alert(numb1 + numb2);
代码示例4:数字+数字
var numb1 = 10;
var numb2 = 20;
alert(numb1 + numb2);
对于防止出现错误,我们还是将数字进行计算的时候加上强制转换:
var numb1 = "10";
var numb2 = 20;
alert(parseInt(numb1) + numb2);
2.5 基本数据类型
- number: 数字,整数/小数
- boolean: true/false
- string: 字符串
- undefined: 只有唯一的值:undefined,表示未定义的变量的值
- null: 只有唯一的值null,表示定义的变量为空值
2.5.1 数字
JS中的数字不区分整形和浮点型, 统一都是number
类型, 与Java一样, 支持用二进制, 八进制, 十六进制的表示.
let a = 0o66; //八进制整数,以0o开头
let b = 0xa; //十六进制整数,以0x开头
let c = 0b10; //二进制整数,以0b开头
JS中的有关数字运算结果可能出现一些特殊的数字值, 有如下几种:
- infinity:无穷大,大于任何数字,(一个数超过js的表示范围,并不会像c或者java的轮回机制,而是给了一个无穷大的值)
- -infinity:负无穷大,小于任何数字
- NaN:表示当前的结果不是一个数字 —— not a number
let max = Number.MAX_VALUE;
// 得到 Infinity
console.log(max * 2);
// 得到 -Infinity
console.log(-max * 2);
// 得到 NaN
console.log('hehe' - 10);
NaN的判断函数:
isNaN();判断是不是一个非数字
思路比较绕,是一个数返回false,不是一个数返回true
var numb1 = "abc"; alert(isNaN(parseInt(numb1)));
记住js中隐式转化很不靠谱,所以还是自动强制转化来的好~~
2.5.2 字符串
字符串字面值需要使用引号引起来, 单引号双引号均可, JS中的字符串和Java一样, 可以使用+
运算符进行不同类型的字符串拼接, 可以使用变量名.lenght
求得字符串的长度.
let s = "hello";
console.log(s.length);
let b = 66;
console.log(s+b);
2.5.3 布尔类型
JS中布尔类型和C语言类似, true
和非0
表示可以表示真, false
和0
可以表示假,Boolean 参与运算时当做 1 和 0 来看待
console.log(true + 1);
console.log(false + 1)
2.5.4 undefined类型和null类型
变量没有被初始化,就是undefined
var a;
alert(a);
可以和字符串进行拼接:
var a;
alert(a + "10");
和数字相加:
var a;
alert(a + 10);
null
与undefined
不同, 它表示变量初始化了, 但值为null, null和undefined都表示取值非法的情况, 但是侧重点不同, null
表示当前的值为空, undefined
表示当前的变量未定义.
let b = null;
console.log(b + 10); // 10
console.log(b + "10"); // null10
2.6 运算符
由于js的运算符大部分与java相似,此处只讲js中特别的~
==
与!=
: 表示比较两个变量的值是否相等.===
与!==
: 表示比较变量的值与类型是否相等.
let a = 10;
let b = "10";
console.log(a == b);//true
console.log(a === b);//false
JS中a==b
这个判断其实触发了隐式类型转换, 也就是说, JS中针对不相同的类型进行比较(==
)运算, 会尝试尽可能的转成相同类型, 而使用===
不会触发隐式类型转换了, 所以有了上面的结果.
像JS这种, 比较能支持隐式类型转换的语言, 称为 “弱类型” 语言; 反过来像Java这种, 不太支持隐式类型转换的语言就被称为 “强类型” 语言.
2.7 数组
2.7.1 数组的创建
let arr1 = new Array(); //很少这样写
let arr2 = [];
let arr3 = [1,2,3,4,5,6,7,8,9,0];
let arr4 = [1, 'hello', this, [1,'hhh'], null, undefined];
JS中使用[]
来表示数组, 同时JS中数组的元素类型不要求是统一的, 可以是任意的类型, 动态类型的语言基本上都如此
输出:console.log(数组名);
console.log(arr1);
console.log(arr2);
console.log(arr3);
console.log(arr4);
JS中的数组也是通过下标的方式来访问的, 所以还可以使用下面几种for
循环来进行遍历.
let arr = [1,2,3,4,5,6,7,8,9,0];
//写法1
/*for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}*/
//写法2
/*for (let i in arr) {
// 此处的 i 是数组下标
console.log(arr[i]);
}*/
//写法3
for (let elem of arr) {
// 此处 elem 是数组元素
console.log(elem);
}
2.7.2 数组越界
在JS中数组的越界访问是合法的, 不会像Java一样报空指针异常, 得到的结果是undefined
let arr = [1,2,3,4,5,6,7,8,9,0];
console.log(arr[100]);
console.log(arr[-1]);
除了越界访问, 越界修改数组的值也是合法的, 此时数组的长度也会随之发生改变.
let arr = [1,2,3,4,5,6,7,8,9,0];
arr[100] = 66;
console.log(arr);
观察结果可以发现, 当数组越界访问将下标为100
的位置的值修改为66
时, 数组的长度就变成了101
, 那么中间未初始化的元素值就都为undefined
了.
如果上面的你可以理解,那么这个十天写出来的语言,接下来会打破你的认知!!!
JS在数组中可以将任意类型作为数组的下标向其中添加元素, 比如负数, 字符串等作为下标, 如下代码:
let arr = [1,2,3,4,5,6,7,8,9,0];
arr[-1] = -1;
arr['hello'] = 'JS';
console.log(arr);
观察结果可以看到, 此时虽然将两个值成功添加到了数组中, 但数组的长度并没有发生改变, 实际上, JS中的数组不仅仅只是一个传统意义的数组(只能按下标来访问元素), 当使用负数, 字符串这些去访问数组时, 会生成一个键值对添加到数组中, 它更像是数组+Map的结合体, 这就得数组也能够按照Map键值对的方式来存储数据
2.7.3 插入/删除/修改元素
可以使用push
方法给数组进行尾插式的添加元素.
let arr = [1,2,3,4,5];
arr.push(6);
arr.push(7);
arr.push(8);
arr.push(9);
arr.push(0);
console.log(arr);
splice
, 它可以完成对数组的插入, 修改, 删除等操作.
array.splice(index, howmany, item1, ....., itemX);
它有三个部分的参数, index
是必须要有的, 表示在什么位置添加/删除元素, howmany
是可选参数, 表示要删除的元素的个数, item1, …, itemX
是可选的变长参数, 表示要添加到数组中的新元素.
修改元素:
let arr = [1,2,3,4,5,6,7,8,9,0];
console.log(arr);//修改前
arr.splice(2, 3, 111, 222, 333);//表示从下标2修改,修改3个元素
console.log(arr);
添加元素:
let arr = [1,2,3,4,5,6,7,8,9,0];
console.log(arr);//插入前
arr.splice(2, 0, 888);//表示在2下标插入一个666
console.log(arr);
删除元素:数组的删除,除了pop和shift外,用splice
var arr = [1, 'a', 2.5, true, undefined, null];
arr.splice(1, 2);
for(var x of arr) {
console.log(x);
}
2.8 条件语句
2.8.1 if语句语法格式:
// 形式1
if (条件) {
语句
}
// 形式2
if (条件) {
语句1
} else {
语句2
}
代码示例1:判定一个数字是奇数还是偶数
var num = 10;
if (num % 2 == 0) {
console.log("num 是偶数");
} else {
console.log("num 是奇数");
}
2.8.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("输入有误");
}
2.9 函数
JS中需要使用function
关键字来声明一个函数, 结构包括函数名, 形参列表(不必写参数类型), 函数体; 不必写返回值类型, 但是可以返回值的.
语法格式:
// 创建函数/函数声明/函数定义
function 函数名(形参列表) {
函数体
return 返回值;
}
// 函数调用
函数名(实参列表) // 不考虑返回值
返回值 = 函数名(实参列表) // 考虑返回值
hello();
function hello() {
console.log("hello");
}
hello();
函数的调用可以出现在函数声明之前, 也可以出现在函数声明之后.
在JS中调用函数传入的实参个数比形参多或者是少都是没关系的, 只不过如果是少的话没有收到传入参数值的变量默认值就为undefined
了, 此时进行数值运算结果就为NaN
了; 而如果是多的话形参中只能拿到形参个数的值, 后面的就拿不到不会参与运算了.
function add(x, y) {
return x + y;
}
console.log(add(10));
console.log(add(10, 20));
console.log(add(10, 20, 30));
console.log(add(10, 20, 30, 40));
获取参数列表:
- 在函数中,隐藏了一个属性,就是参数列表数组:arguments
function add(x, y) {
let result = 0;
for (let elem of arguments) {
if (elem !== undefined) {
result += elem;
}
}
return result;
}
console.log(add(10));
console.log(add(10, 20));
console.log(add(10, 20, 30));
console.log(add(10, 20, 30, 40));
2.10 作用域
全局作用域: 在整个 script 标签中, 或者单独的 js 文件中生效.
局部作用域/函数作用域: 在函数内部生效.
var num = 10;
console.log(num);
function test1() {
var num = 20;
console.log(num);
}
function test2() {
num = 30;
console.log(num);
}
test1();
test2();
console.log(num);
2.11 对象
1. 使用 字面量 创建对象 [常用]
访问属性可以使用.
或[ ]
, 使用[ ]
访问属性, 此时属性需要加上引号, 调用方法要记的加上()
.
var a = {}; // 创建了一个空的对象
var student = {
name: 'xyk',
height: 180,
weight: 130,
sayHello: function() {
console.log("hello");
}
};
console.log(student.name);
console.log(student['height']);
console.log(student.weight);
student.sayHello();
2.使用 new Object 创建对象
var student = new Object(); // 和创建数组类似
student.name = "xyk";
student.height = 180;
student['weight'] = 130;
student.sayHello = function () {
console.log("hello");
}
console.log(student.name);
console.log(student['weight']);
student.sayHello();
三、Java对象与JavaScript对象的区别
3.1 JavaScript 没有 "类" 的概念
对象其实就是 "属性" + "方法" .
类相当于把一些具有共性的对象的属性和方法单独提取了出来, 相当于一个 "月饼模子"
在 JavaScript 中的 "构造函数" 也能起到类似的效果.
而且即使不是用构造函数, 也可以随时的通过 { } 的方式指定出一些对象在 ES6 中也引入了 class 关键字, 就能按照类似于 Java 的方式创建类和对象了
3.2 JavaScript 对象不区分 "属性" 和 "方法"
JavaScript 中的函数是 "一等公民", 和普通的变量一样. 存储了函数的变量能够通过 ( ) 来进行调用执行.
3.3 JavaScript 对象没有 private / public 等访问控制机制
对象中的属性都可以被外界随意访问.
3.4 JavaScript 对象没有 "继承"和“多态”
- 没有类,当然没有继承和多态
- 你最多能做的是,“嵌套对象”