JavaScript 基础
文章目录
JavaScript
初识JavaScript
JavaScript 和 Java 是什么关系呢?
就是老婆和老婆饼的关系, 也就是没什么关系
JS 最初只是为了进行前端页面开发, 后来 JS 被赋予了更多的功能, 也可以用来开发桌面程序, 手机APP, 服务器端的程序
JS 和 Java 也有一些相同之处
- HTML: 网页的结构(骨)
- CSS: 网页的表现(皮)
- JavaScript: 网页的行为(魂)
JS 是运行在浏览器上的, 比如 Chrome 里面就专门有一个模块, 就是JS引擎, 就相当于 JVM
一样, 能够解释执行 JS 代码. 后来就有大佬把这部分代码单独拿出来了,封装成独立的程序了, 称为 V8 引擎.
这样 JS 的使用范围也就更广了, 不在限于浏览器了.
JavaScript 的组成
- ECMAScript(简称 ES): JavaScript 语法
- DOM: 页面文档对象模型, 对页面中的元素进行操作
- BOM: 浏览器对象模型, 对浏览器窗口进行操作
DOM API 是浏览器给JS提供的操作页面元素的 api
BOM API 是浏览器给JS提供的操作浏览器窗口的api
第一个程序
编写 hello world 程序
通过 Script 标签嵌入到 html 里面
<script>
alert('hello world')
</script>
三种引入方式
- 内部 js , 就是上面演示的 script 便签
- 外部 js 写成一个单独的 .js 文件
alert('hello world')
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="app.js"> </script>
<script>
// alert('hello world')
</script>
</body>
</html>
注释:
html: < !-- – >
css: /* */
js: // , / * */
- 行内 js , 直接写到 html 元素内部
<body>
<div onclick="alert('hello world')">
这是一个div, 点我一下试试
</div>
alert 能够弹窗, 从而让用户看到程序的输出, 但是弹框操作不太友好, 这个框弹出来就不能进行其他操作了, 这种框叫做 模态对话框.
我们使用 console.log 就可以在控制台中打印日志
<script>
console.log('hello world');
</script>
js 里这个 console.log 就类似 Java 中的 println 一样, 也是一个非常有用的调试手段.
语法
变量的使用
var 变量名 = 初始值;
<script>
var a = 10;
var b = 'hello'
console.log(a)
console.log(b)
</script>
js 定义变量不必写类型, 不写类型不意味着"没有类型", 而是变量的类型是通过初始化操作的值来确定的.
上述的 a 就是 number 类型(JS 不区分 int double 同意都叫做 number)
b 就是 string 类型
JS 里定义变量使用的关键字还可以是 let
var 是老式的写法(可能有坑)
let 是新式写法, 规则更接近 C++ Java 等主流语言
var a = 10;
var a = 10;
console.log(a);
这还是能够运行, 这就可能出现问题
如果用 let 就好了, 就能给你避免一些问题
细说还是有很多区别, 这里我们可不用纠结, 我们只要无脑用 let 就好了, 在别的地方见到 var 知道是啥就好了.
动态类型
var a = 10;
console.log(a)
a = 'hello'
console.log(a)
一个变量在程序运行过程中, 类型可以发生改变, 这就是动态类型(JS, Python, PHP…)
一个变量在程序运行过程中, 类型不能发生改变, 这就是静态类型(C++, Java,Go…)
动态类型的好处就是代码非常灵活
假如使用Java写两个数相加, 可能就得写多个方法, 用重载实现, 而动态类型的话写一个方法即可
坏处就是, 一个变量当下到底是啥类型, 里面存了什么值, 里面提供哪个方法哪些属性就是不确定的,
基本数据类型
JS 中内置的几种类型
- number: 数字. 不区分整数和小数.
- boolean: true 真, false 假.
- string: 字符串类型.
- undefined: 只有唯一的值 undefined. 表示未定义的值.
- null: 只有唯一的值 null. 表示空值.
number 数字类型
JS 中不区分整数和浮点数, 统一都使用 “数字类型” 来表示.
var a = 07; // 八进制整数, 以 0 开头
var b = 0xa; // 十六进制整数, 以 0x 开头
var c = 0b10; // 二进制整数, 以 0b 开头
string 字符串类型
基本规则
字符串字面值需要使用引号引起来, 单引号双引号均可
var a = "haha";
var b = 'hehe';
var c = hehe; // 运行出错
转义字符
有些字符不方便直接输入, 于是要通过一些特殊方式来表示
- \n
- \
- ’
- "
- \t
求长度
使用 String 的 length 属性即可
var a = 'hehe';
console.log(a.length);
var b = '哈哈';
console.log(b.length);
字符串拼接
使用 + 进行拼接
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 意义重大, 往往要搭配条件/循环完成逻辑判断.
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
运算符
JavaScript 中的运算符和 Java 用法基本相同.
这里说两个不一样的
- === 比较相等(不会进行隐式类型转换)
- !==
let a = 10;
let b = '10';
console.log(a==b);
console.log(a===b);
console.log(a==b); 这个代码中出触发了"隐式类型转换"
在 JS 中, 针对不同类型的值进行比较/运算, 会尝试尽可能转化为相同类型的值
console.log(a===b); 这个 === 就不会进行类型转换
像 Java 这种, 不太支持隐式类型转换的语言, 称为"强类型"语言
像 JS 这种, 比较能支持隐式类型转换的语言, 称为"弱类型"语言
数组
创建数组
使用 new 关键字创建
// Array 的 A 要大写
var arr = new Array();
使用字面量方式创建 [常用]
var arr = [];
var arr2 = [1, 2, 'haha', false]; // 数组中保存的内容称为 "元素"
注意: JS 的数组不要求元素是相同类型.
let arr3 = [1,2,3,4,5];
console.log(arr3);
arr3[0] = 6;
console.log(arr3);
那我们要是打印超出数组范围的值呢?
console.log(arr3[100]);
console.log('还在继续执行');
<script>
let arr3 = [1,2,3,4,5];
arr3[0] = 6;
console.log(arr3);
console.log(arr3[100]);
arr3[100] = 666;
console.log(arr3);
arr3[-1] = 999;
console.log(arr3);
arr3['hello'] = 1234;
console.log(arr3);
console.log('还在继续执行');
</script>
JS 的数组, 不仅仅是一个传统的数组了(只能按照下标取元素), 而是一个带有"键值对"性质的东西了.
数组的遍历
<script>
let arr3 = [1,2,3,4,5];
for(let i = 0; i < arr3.length; i++) {
console.log(arr3[i]);
}
for(let elem of arr3) {
console.log(elem);
}
for(let i in arr3) {
console.log(arr3[i]);
}
</script>
给数组添加元素
使用 push 方法
arr3.push(666);
删除元素
splice
这个方法是一个万能方法
可以用来插入, 修改, 删除
splice(startIndex, count, 变长参数…)
把后面变长参数的内容, 替换到前面指定区间内
如果后面没有变长参数, 就相当于删除
如果后面变长参数和前面指定的区间个数一样, 此时就是修改/替换
如果后面变长参数比前面的区间个数常, 此时就是新增
<script>
let arr = [1,2,3,4,5];
// 删除2下边开始的1个值
arr.splice(2,1)
console.log(arr);
// 替换2下标的一个值
arr.splice(2,1,666);
console.log(arr);
// 2下标插入一个值
arr.splice(2,0,888);
console.log(arr);
</script>
函数
/ 创建函数/函数声明/函数定义
function 函数名(形参列表) {
函数体
return 返回值;
}
// 函数调用
函数名(实参列表) // 不考虑返回值
返回值 = 函数名(实参列表) // 考虑返回值
<script>
function hello() {
console.log('hello');
}
hello();
</script>
<script>
function add(x,y) {
return x + y;
}
let a = add(3.5, 9);
console.log(a);
</script>
函数定义并不会执行函数体内容, 必须要调用才会执行. 调用几次就会执行几次.
function hello() {
console.log("hello");
}
// 如果不调用函数, 则没有执行打印语句
hello();
调用函数的时候进入函数内部执行, 函数结束时回到调用位置继续执行. 可以借助调试器来观察.
函数的定义和调用的先后顺序没有要求. (这一点和变量不同, 变量必须先定义再使用)
// 调用函数
hello();
// 定义函数
function hello() {
console.log("hello");
}
<script>
function add(x,y) {
return x + y;
}
let a = add(3.5, 9);
let b = add('hello','world');
let c = add(true,2);
let d = add(undefined,10);
let e = add(undefined,'10');
console.log(a);
console.log(b);
console.log(c);
console.log(d);
console.log(e);
</script>
NaN 是not a number 的意思
如果实参个数少于形参个数, 多出来的形参的值就是 undefined
如果实参个数多余形参个数, 多出来的实参就没用上
实参和形参个数不匹配是不会报错的, 只会尽可能去执行.
支持n个参数的求和:
<script>
function add() {
let result = 0;
for (let elem of arguments) {
result += elem;
}
return result;
}
let a = add(1,2,3,4,5);
let b = add(3,5,6,7,8,9,0,5,3,2,5)
console.log(a);
console.log(b);
</script>
对于JS这样的动态语言来说, 不需要"重载" 这样的语法
函数表达式
<script>
let add = function() {
let result = 0;
for (let elem of arguments) {
result += elem;
}
return result;
}
</script>
先定义了一个没有名字的匿名函数, 然后把匿名函数赋值给一个 add 变量了.
add变量的类型, 就叫做 function 类型
<script>
let add = function() {
let result = 0;
for (let elem of arguments) {
result += elem;
}
return result;
}
// 获取变量的类型
console.log(typeof(add));
</script>
JS 中, 可以像普通变量一样, 把函数赋值给一个变量,同时, 也可以把函数作为另一个函数的参数, 或者把函数作为另一个函数的返回值(这一点在Java是无法做到的)
这个特性, 称为在j s 中是"一等公民"
<script>
function two() {
return 100;
}
function one() {
return two();
}
</script>
JS 中变量的作用域
当代码中访问某个变量的时候, 要去哪里找这个变量呢?
JS 会先找到当前作用域, 如果当前没有, 就往上层作用域找, 一直往上找到全局作用域, 如果还找不到, 就报错/undefined
<script>
let num = 1;
function test1() {
let num = 2;
function test2() {
let num = 3;
console.log("test2: " +num);
}
test2();
console.log("test1: " + num);
}
test1();
console.log("global: " + num);
</script>
<script>
let num = 1;
function test1() {
let num = 2;
function test2() {
// let num = 3;
console.log("test2: " +num);
}
test2();
console.log("test1: " + num);
}
test1();
console.log("global: " + num);
</script>
当前作用域没找到的话, 就会往上找
这个语法设定和Java中的变量捕获有点类似
对象
JS 不是面向对象的编程语言, 但是存在对象的概念, 这就意味着 JS 中关于对象的设定和 Java 差别很大
JS 中没有封装, 继承, 多态, 甚至没有类
JS 中没有类, 所有对象类型都是Object
使用 字面量 创建对象 [常用]
<script>
let student = {
name: '蔡徐坤',
age: 25,
height: 180,
weight: 70,
sing: function() {
console.log("鸡你太美");
},
dance: function() {
console.log('铁山靠');
},
};
console.log(student.age);
console.log(student.height);
student.sing();
student.dance();
</script>
使用 new Object 创建对象
<script>
let student = new Object();
student.name = "蔡徐坤";
student.height = 180;
student.age = 25;
student.sing = function() {
console.log("鸡你太美");
}
student.dance = function() {
console.log('铁山靠');
}
console.log(student.age);
console.log(student.height);
student.sing();
student.dance();
</script>
JS 中的对象里面有啥属性, 有啥方法, 都不是提前约定好的, 而是随时可以添加.