目录
1.初识JavaScript
1.1背景知识
JavaScript简称js,是世界上最流行的编程语言之一.
是一个脚本语言, 通过解释器运行
主要在客户端(浏览器)上运行, 现在也可以基于 node.js 在服务器端运行
JS和html和css的关系
html: 网页的结构
css:网页的表皮
JS:网页的灵魂
JS最初只是为了进行前端页面的开发,后来又被赋予其他的功能,可以用来开发桌面程序,手机app,服务器程序
它和Java编程语言还是有不少关系的,比如在chrome里专门有一个模块.JS引擎,就相当于JVM能识别并运行.class文件一样,能够解释执行JS代码.后来这部分代码被独立出来,封装成独立的程序了(V8引擎),此时JS的适用范围广了.
JS代码具体是如何运行的呢?
程序员编写的代码是保存在文件中的,存储在硬盘上,双击.html文件浏览器就会读取文件,把文件内容加载到内存中,浏览器会解析代码,翻译成二进制让计算机识别(解释器的工作),得到的二进制指令会被CPU加载并执行
这一系列的加载翻译执行的过程都是由浏览器执行的
浏览器分为渲染引擎+JS引擎
渲染引擎:解析html+css,俗称为"内核"
JS引擎:也就是JS解释器.典型的就是V8引擎
JavaScript的组成
ECMAScript(简称 ES): JavaScript 语法
DOM: 页面文档对象模型, 对页面中的元素进行操作
BOM: 浏览器对象模型, 对浏览器窗口进行操作
我们主要学习前ES,还有DOM的常用API
我们尝试写第一个JS程序
<body>
<script>
alert("你好!");
</script>
</body>
JavaScript 代码可以嵌入到 HTML 的 script 标签中
1.2JS的三种书写方式
行内式
直接嵌入到html元素内部
<input type="button" value="点击" onclick="alert('hello!')">
注意:JS 中字符串常量可以使用单引号表示, 也可以 使用双引号表示. HTML 中推荐使用双引号, JS 中推荐使用单引号.
内嵌式
写到script标签中
<body>
<script>
alert("你好!");
</script>
</body>
外部式
写到单独的.js文件中
引入.js文件
执行
注意:
script 标签中间不能写代码. 必须空着(写了代码也不会执行).外部式适合代码多的情况
alert能够弹窗,从而让用户看到程序的输出,但是也有不好的地方,有些对话框一弹出来,就会阻止界面的其他部分,也操作不了页面的其它部分,叫做模态对话框
JS中的console.log就可以在控制台进行打印日志,类似于Java中的println一样,也是一种有用的调试手段
输入输出
alert:弹出一个对话框输出结果
prompt:弹出一个输入框输入
还有,html,css,js的注释方式是不相同的
html:<!-- 注释内容 -->
css:/*注释内容*/
js:// 注释内容 /*注释内容*/
2.语法简介
2.1变量的使用
js定义变量不用写类型,但是不意味着没有类型,而是变量的类型是通过初始化操作的值来确定的
变量创建方法
var 变量名 = 值;
var 是 JS 中的关键字, 表示这是一个变量.
= 在 JS 中表示 "赋值", 相当于把数据放到内存的盒子中.
= 两侧建议有一个空格 每个语句最后带有一个 ;
初始化的值如果是字符串, 那么就要使用单引号或者双引号引起来
变量定义还可以写 let 变量名 = 值;
var属于老式的写法,let是新式写法
看一个例子:
<body>
<script>
var name = prompt("姓名:");
var age = prompt("年龄:");
var score = prompt("分数");
alert("姓名是:"+ name + "\n" + "年龄是:" + age + "\n" + "分数是:" + score + "\n" );
</script>
</body>
+ 表示字符串拼接, 也就是把两个字符串首尾相接变成一个字符串.
\n 表示换行
动态类型
JS是动态类型语言,一个变量在程序中,类型可以发生改变,就是动态类型语言(JS,python,PHP...)
运行过程中变量不能发生类型改变就是静态类型(C,java,C++,GO...)
动态类型的特点
1.js的变量类型是程序运行过程中才确定的,运行到=才会确定类型
2.随着程序运行,变量类型可能会发生改变
2.2基本数据类型
js中内置的几种基本数据类型:
number: 数字.JS 中不区分整数和浮点数, 统一都使用 "数字类型" 来表示
Infinity: 无穷大, 大于任何数字. 表示数字已经超过了 JS 能表示的范围.
-Infinity: 负无穷大, 小于任何数字. 表示数字已经超过了 JS 能表示的范围.
NaN: 表示当前的结果不是一个数字.(not a number)
boolean: true 真, false 假.
Boolean 参与运算时当做 1 和 0 来看待
string: 字符串类型.字符串字面值需要使用引号引起来,单引号双引号均可
如果字符串中本来就有引号怎么办?
有些字符不方便输入,就需要用到转义字符
\n :换行
\\ : \
\' : '
\" : "
\t : 空格
undefined: 只有唯一的值 undefined. 表示未定义的值.
null: 只有唯一的值 null. 表示空值.
注意:
null 和 undefined 都表示取值非法的情况, 但是侧重点不同.
null 表示当前的值为空. (相当于有一个空的盒子) undefined 则表示当前的变量未定义. (相当于连盒子都没有)
js中的运算符和Java中的大多比较类似
== 比较相等(会进行隐式类型转换)
此处出发了隐式类型转换,js中针对不同的类型进行比较/运算,会尝试将不同的转换成相同的类型
这里将true转换成了1
=== 比较相等(不会进行隐式类型转换)
像Java这种不太支持隐式类型转换的语言称为强类型语言
JS这种支持隐式类型转换的语言称为弱类型语言
我们看一下各种语言的分类
C++由于要和C兼容,因为C支持隐式类型转换,所以C++也得支持,业界的共识是强类型比弱类型好,类型强说明类型间的区分度就高.编译器能做的检查工作就多,代码就不容易出错
2.3数组
js数组创建方式
1.使用 new 关键字创建
2.使用字面量方式创建 [常用]
let arr = new Array();
let arr2 = [];
let arr3 = [1,'hello',true,[]];
js数组中元素类型不要求统一,可以是任意类型,不仅仅js如此,动态类型的语言都是如此.那么底层是如何做到存储这些不同的类型的变量呢?
站在c语言的视角,每个js变量都有一个地址(唯一的身份标识),数组存储的其实是对应的身份标识,身份标识是统一格式的内容,在底层用一个c的数组来存储这些身份标识,在js层面就相当于保存了不同类型的变量
操作数组:访问下标
let arr = ['微机原理','Javaee','程序设计基础'];
console.log(arr[0]);
console.log(arr[1]);
console.log(arr[2]);
console.log(arr);
控制台打印:
如果我们打印arr[100]是什么效果?
console.log('-------------------');
console.log(arr[100]);
显示未定义.此时我们给100赋值
我们可以看到.赋值成功了,中间empty x 97代表着中间还有97个位置是空的
我们再来看个奇怪的下标
看到这里,你会发现,js的数组不是传统的数组了(只能按照下标取元素).它是带有键值对性质的数组
就像是Map+数组,很多动态类型的语言都是如此,,不过python数组没有这么灵活.在计算机中灵活就意味着容易出错,因此js的更高版本引入了专门的map来表示键值对.
遍历方式
//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);
}
添加元素:尾插
删除元素:splice
这个方法相当于一个万能方法,可以用来插入,修改,删除....
splice(startIndex,count,变长参数...)
函数意思是:将变长参数的内容,替换到前面指定的区间,从start开始替换count个
如果后面没有变长参数,就相当于删除操作
如果变长参数和前面指定的区间个数一样,那就是替换
如果变长参数比前面区间个数长,就是新增元素
删除:
新增:
替换:
2.4函数
格式
创建函数/函数声明/函数定义
function 函数名(形参列表) {
函数体
return 返回值;
}
函数调用
函数名(实参列表) // 不考虑返回值
返回值 = 函数名(实参列表) // 考虑返回值
我们先来写一个函数
function add(x,y){
return x+y;
}
开头有函数关键字,function,函数名add,形参列表(x,y).
我们看到,形参列表参数没有类型,也就是什么类型的都可以,只要传入的变量能够在函数内部正常工作即可
也没有返回值类型,像java中的public static.....都没有
另外,函数形参和实参的个数可以不匹配,但是实际开发要求匹配.当实参和形参个数不匹配的时候,是不会报错的,会尽可能去执行
如果实参个数比形参个数多,那么多出来的不参与函数运算
我们可以看到,并没有将30进行运算
如果实参个数比形参个数少, 则此时多出来的形参值为 undefined
NaN:not a number
对于js这样的动态类型语言,是不需要重载这样的语法的,我们看下面这个函数
function add(){
let result = 0;
for(let elem of arguments){
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));
函数表达式
指把一个匿名函数赋值给一个变量,然后就可以通过这个变量来调用函数了.
js中可以像普通变量一样,将函数赋值给一个变量,同时也可以将函数作为另一个函数的参数,或者把函数做为另一个函数的返回值,java是做不到的,这个特性称为"一等公民"
还是相同的结果,add变量的类型,就叫做function类型,对于function类型的变量是可以调用的
作用域
指某个标识符名字在代码中的有效范围.
全局作用域: 在整个 script 标签中, 或者单独的 js 文件中生效.
局部作用域/函数作用域: 在函数内部生效.
看个例子:
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('golbal: '+ num);
</script>
js会先找当前作用域,如果当前没有,就会往上层作用域找,一直往上层直到全局作用域(从内到外依次进行查找)如果还没找到就会报错/undefined ,这个语法类似于java中的变量捕获
2.5对象
js不是面向对象语言,但是存在对象的概念,所以这里的对象和jjava中的对象差异是很大的
在 JS 中, 字符串, 数值, 数组, 函数都是对象.
每个对象中包含若干的属性和方法. 属性: 事物的特征. 方法: 事物的行为
使用 字面量 创建对象 [常用]
let a = {}; // 创建了一个空的对象
let b = {
name:'zhangsan',
age:18,
scoer:59,
sayHello: function() {
console.log("hello");
}
};
使用 { } 创建对象
属性和方法使用键值对的形式来组织
键值对之间使用 , 分割.最后一个属性后面的 , 可有可无
键和值之间使用 : 分割
方法的值是一个匿名函数
使用对象的属性和方法
使用 new Object 创建对象
let b = new Object();
b.name = 'zhangsan';
b.age = 18;
b['score'] = 90;
b.sayHello = function () {
console.log("hello");
}
// 1. 使用 . 成员访问运算符来访问属性 `.` 可以理解成 "的"
console.log(b.name);
// 2. 使用 [ ] 访问属性, 此时属性需要加上引号
console.log(b['score']);
// 3. 调用方法, 别忘记加上 ()
b.sayHello();
注意
使用 { } 创建的对象也可以随时使用 b.name = "zhangsan"; 这样的方式来新增属性.
使用 构造函数 创建对象
前面的创建对象方式只能创建一个对象. 而使用构造函数可以很方便 的创建 多个对象
使用构造函数可以把相同的属性和方法的创建提取出来, 简化开发过程.
基本语法
function 构造函数名(形参) {
this.属性 = 值;
this.方法 = function...
}
var obj = new 构造函数名(实参);
注意:
this 关键字来表示当前正在构建的对象.
构造函数的函数名首字母一般是大写的.
构造函数的函数名可以是名词.
构造函数不需要 return
创建对象的时候必须使用 new 关键字
看一个例子
function Dog(name, type, sound) {
this.name = name;
this.type = type;
this.wang = function () {
console.log(sound); // 别忘了作用域的链式访问规则
}
}
let dabai = new Dog('dabai','柴犬','汪');
let erbai = new Dog('erbai','哈士奇','汪汪汪');
console.log(dabai);
dabai.wang();
new关键字的理解
new 的执行过程: 先在内存中创建一个空的对象, this 指向刚才创建的空对象(将上一步的对象作为 this 的上下文) ,然后 执行构造函数的代码, 给对象创建属性和方法 ,最后 返回这个对象 (构造函数本身不需要 return, 由 new 代劳了)