目录
一:初识JAVASCRIPT
1:编程语言
就是让计算机解决某个问题而使用的某种程序设计语言程序代码,并最终得到结果的过程。
计算机程序:就是计算机一系列指令的集合,而程序是我们掌握的语言来编写的,所以要控制计算机,就要用计算机语言向计算机发出指令。
2:计算机语言
计算机语言:指用于人与计算机通讯的语言,它是人与计算机之间传递信息的媒介。计算机语言可以分为三大类机器语言、汇编语言、和高级语言三大类。
机器语言:实际上计算机最终执行的都是机器语言,它是由”0“和”1“组成的二进制数。
汇编语言:汇编语言和机器语言实质是相同的,都是直接对硬件操作,只不过指令采用了英文缩写的标识符,容易识别和记忆。
高级语言:高级语言主要是相对于低级语言而言,它并不是特指某一种具体的语言,而是包括了很多编程语言,常用的有C语言、C++、Java、C#、Python、PHP、JavaScript等。
总结:
- 高级语言的程序不能被计算机识别,需要经过翻译器转化为机器语言,也就是1和0;
- 编程语言和标记语言的区别,编程语言有很强的逻辑是主动的,标记语言不向计算机发出指令是被动的;
3:存储单位
位(bit): 1bit 可以保存1或者0(最小单位); 字节(Byte): 1B = 8b 千字节(KB): 1KB = 1024B 兆字节(MB): 1MB = 1024KB 吉字节(GB): 1GB = 1024MB 太字节(TB): 1TB = 1024GB |
4:JavaScript是什么
JavaScript是世界上最流行的语言之一,是运行在客户端的脚本语言,它不需要编译,由js引擎解释并执行,现在基于Node.j也可以进行服务端编程。
作者:布兰登·艾奇(Brendan Eich),最初命名为LiveScript,后来在与sun公司合作后改名为Javascript。
作用:表单验证、网页特效、服务端开发、桌面程序、APP、控制硬件、游戏开发。
组成:ECMAScript是由ECMA国际(原欧洲计算机制造协会)进行标准化的一门编程语言,这种语言在万维网上应用广泛,被称为javascript(网景公司)和jscript(微软公司),它规定了编程语法和基础核心知识,是所有浏览器厂商共同遵守的一套JS语法工业标准。
二:JAVASCRIPT基础
浏览器分成两个部分:渲染引擎和JS引擎。
渲染引擎:用来解析HTML与CSS,俗称内核。
JS引擎:js解释器,用来读取网页种的js代码,然后对其处理,chrome的浏览器的v8,浏览器本身是不会执行JS代码,通过JS引擎解释,交给计算机去执行(逐行解释执行)。
JS组成
JS是由三部分组成:JS语法、文档对象(DOM)、浏览器对象(BOM)。
DOM对象:是W3C组织推荐的处理可扩展标记语言的标准编程接口。通过 DOM 提供的接口可以对页面上的各种元素进行操作(大小、位置、颜色等)。
BOM对象:通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率等。
JS初体验
JS有三种书写方式:行内、内嵌、外部。
行内:
<input type=”button” name=”username” value=”用户名” onclick=”alert(‘你好’)”/>
缺点:
- 可读性差, 在html中编写JS大量代码时,不方便阅读;
- 引号易错,引号多层嵌套匹配时,非常容易弄混;
- 特殊情况下使用;
内嵌:
<script>
alert(“你好”);
</script>
在老的版本中,<script type=”text/javascript”></script>,在HTML5中script默认就是js不需要再声明type=”text/javascript”。
外部:
<script src="my.js"></script>
- 利于HTML页面代码结构化,把大段 JS代码独立到 HTML 页面之外,既美观,也方便文件级别的复用
- 引用外部 JS文件的 script 标签中间不可以写代码
- 适合于JS 代码量比较大的情况
JS注释
单行注释:// 不想被js引擎执行的,注释起来。
多行注释:/* */
/*
第一行注释
第二行注释
*/
JS输出语句
1:alert(msg) 浏览器弹出警示框 |
2:console.log(msg) 浏览器控制台输出信息,给开发人员看的 |
3:prompt(info,defaulttxt) 浏览器弹出输入框接收用户信息。(提示信息,默 认信息) |
JS变量
变量名是用来存取数据的容器,我们通过变量名来获取数据,数据是可以修改的。变量是程序在内存中申请的一块存放数据的空间。
变量的声明:
var myname = “小明”;
var:是声明一个变量,js的关键词。
myname:声明的一个变量名,开发人员定义。
小明:给变量myname赋值。
同时声明多个变量,用”,”隔开,如下:
var name=”小明”,age=13,sex=”男”;
变量重新赋值:name=”李四”;
总结:
- 声明变量用var,多个变量用英文逗号隔开,变量可重新赋值。
- 严格区分大小写。var name; 和 var Name; 是两个变量。
- 不能以数字开头,不能是js关键词比如 var、for、while等。
- 驼峰命名法,如myName,第一个字母小写,第二个字母大写,变量名需有意义。
数据类型
在计算机中不同的数据所需占用的存储空间是不同的,所以为了充分利用存储空间,我们为数据设置不同的数据类型,比如:“小明”,18。
JavaScript 是一种弱类型或者说动态语言。这意味着不用提前声明变量的类型,在程序运行过程中,类型会被自动确定。
比如:
myname=”小明” //字符串
age = 18 //数字类型
Js判断右边值是来判断,确定变量值得类型。Js的数据类型有如下两大类:
简单数据类型:
Number |
String |
Boolean |
Undefined |
Null |
Number数字类型
数字型进制
表示整数的方法有10进制,8进制和16进制。就一般使用的数值而言,16进制是指0-15的数值(0到9,a到f),在JavaScript中,在其前面加"0x",标志其为16进制,8进制是在0-7前面加"0"。
数字型范围
最大值 | 这个值为 |
Number.MAX_VALUE | 1.7976931348623157e+308 |
最小值 | 这个值为 |
Number.MIN_VALUE | 5e-324 |
数字的特殊值
Infinity | 代表无穷大,大于任何数值 |
-Infinity | 代表无穷小,小于任何数值 |
NaN ,Not a number | 代表一个非数值 |
isNaN
用来判断一个变量是否为非数字的类型 ,返回 true 或者 false
var age = 21;
var isNum = isNaN(age);
console.log(isNum); // false
var name= "小明";
console.log(isNaN(name)); // true ,"小明"是一个非数字
String字符串类型
字符串定义
字符串型可以是引号中的任意文本,其语法为 双引号 "" 和 单引号''。
举例:var name = ”小明”; //没有引号会报错
引号嵌套
JS 可以用单引号嵌套双引号 ,或者用双引号嵌套单引号 (外双内单,外单内双)
var myName = “我的姓名是’小明’”;
字符串转义符
字符串中有特殊字符,我们用转义符都是 \ 开头的进行转义。 |
---|
\n :换行符 |
\\ :斜杠\ |
\’: ‘ 单引号 |
\”:双引号” |
\t: tab缩进 |
\b:空格 |
字符串长度
字符串是由若干个字符组成,这些字符的数量就是字符串的长度。
如:
var str = “我是高帅富!”; alert(str.length); //输出是6
字符串拼接
多个字符串之间可以使用 + 进行拼接之后得到新的字符串。
如:
var str = ”路漫漫其修远兮,”,strAll=””;
strAll = str + “吾将上下而求索”;
alert(strAll );//路漫漫其修远兮,吾将上下而求索
alert(100+100);//200
alert(100+”100”); //100100
alert(“100”+”100”);//100100
总结:
- 字符串与数字相加,字符相连。
- 变量也可以和字符相加,变量不能加引号,否则会当成字符串。
布尔型Boolean
布尔类型有两个值:true 和 false ,其中 true 表示真(对),而 false 表示假(错)。
布尔型和数字型相加的时候, true 的值为 1 ,false 的值为 0。
console.log(true + 1); // 2
console.log(false + 1); // 1
Undefined和 Null
Undefined:一个声明后没有被赋值的变量会有一个默认值undefined;
var myName;
console.log(myName); // undefined
console.log('你好' + myName); // 你好undefined
console.log(11 + myName); // NaN
console.log(true + myName); // NaN
Null:一个声明变量给 null 值,里面存的值为空;
var myName= null;
console.log('你好' + myName); // 你好null
console.log(11 + myName); // 11
console.log(true + myName); // 1
获取变量类型
typeof 可用来获取检测变量的数据类型。
var num = 18;
var myname = null;
console.log(typeof num) // 结果 number
console.log(typeof myname) // object
类型转换
比如说,在表单(form)、prompt中提交的信息都是字符串信息,就无法就行加减,这时候就需要数据类型转换。
转换为字符串
toString:
var num = 13; console.log(typeof num.toString());
String:
var num =13;console.log(typeof String(num));
第三种方式字符串拼接:
var num = 13; console.log(typeof 13 + ‘我是字符串’);
数字类型转换
parseInt(string, radix):将string类型转成整数数字类型。
举例:
parseInt("12"); //returns 12
parseInt("12blue"); //returns 12
parseInt("12.8"); //returns 12
parseInt("blue"); //returns NaN
radix可选。表示要解析的数字的基数。该值介于 2 ~ 36 之间。
parseFloat(string) 将string类型转成浮点数数字类型。
Number(string) 将string强制转换成数字类型。
转为布尔类型
代表空、否定的值会被转换为 false ,如 ''、0、NaN、null、undefined,其余值都会被转换为 true。
console.log(Boolean('')); // false
console.log(Boolean(0)); // false
console.log(Boolean(NaN)); // false
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
console.log(Boolean('小白')); // true
console.log(Boolean(12)); // true
总结
- 编译器:是在代码执行之前进行编译,生成中间代码文件,好比:首先把所有菜做好,才能上桌吃饭。
- 解释器:解释器是在运行时进行及时解释,并立即执行(当编译器以解释方式运行的时候,也称之为解释器)好比吃火锅,边吃边涮,同时进行。
- 标识符:就是指开发人员为变量、属性、函数取的名字,标识符不能是关键字或保留字。
- 关键字:是指 JS本身已经使用了的字,不能再用它们充当变量名、方法名。
包括:break、case、catch、continue、default、delete、do、else、finally、for、function、if、in、instanceof、new、return、switch、this、throw、try、typeof、var、void、while、with 等。
- 保留字:实际上就是预留的“关键字”,意思是现在虽然还不是关键字,但是未来可能会成为关键字,同样不能使用它们当变量名或方法名。
包括:boolean、byte、char、class、const、debugger、double、enum、export、extends、fimal、float、goto、implements、import、int、interface、long、mative、package、private、protected、public、short、static、super、synchronized、throws、transient、volatile 等。
三:运算符
运算符也被称为操作符,是用于实现赋值、比较和执行算数运算等功能的符号,常见的运算符:算数运算符,递增和递减运算符,比较运算符,逻辑运算符,赋值运算符。
1:算数运算符
概念:算术运算使用的符号,用于执行两个变量或值的算术运算。
加(+)、减(-)、乘(*)、除(/)、取余(%)
取余(%):返回除法的余数。
注意:浮点数的精度问题
浮点数值的最高精度是 17 位小数,但在进行算术计算时其精确度远远不如整数。
var result = 0.1 + 0.2;
// 结果不是 0.3,而是:0.30000000000000004
console.log(0.07 * 100);
// 结果不是 7, 而是:7.000000000000001
所以:不要直接判断两个浮点数是否相等 !
2:递增和递减运算符
如果需要反复给数字变量添加或减去1,可以使用递增(++)和递减( -- )运算符来完成。
举例:
var num=1;num++;//2
var num=1;++num;//2
放在变量前面时,我们可以称为前置递增(递减)运算符,放在变量后面时,我们可以称为后置递增(递减)运算符。
前置递增:
++num 前置递增,就是自加1,类似于 num = num + 1,简写++num,先自加,后返回值。
var num = 10;
alert(++num + 10); // 21
后置递增:
num++ 就是自加1,类似于 num = num + 1,简写 num++,先返回原值,后自加
var num = 10;
alert(10 + num++); // 20
3:比较运算符
< 小于号 1<2 true |
> 大于号 1>2 false |
>= 大于等于 2>=2 true |
<= 小于等于 3<=2 false |
== 是否相等 2==2 true |
!= 不等号 3!=2 true |
=== 全等号 要求值和数据类型必须相等 |
全等号 要求值和数据类型必须相等举例: “3”===3 false,”3”==3 true |
举例:
console.log(3 >= 5); //false
console.log(2 <= 4); //true
console.log(3 == 5);//false
console.log('中文' == 'chinese'); //false
console.log(10 == 10); //true
console.log(10 == '10');//true
console.log(10 != 10); //false
console.log(10 === 10);//true
console.log(10 === '10'); //false
4:逻辑运算符
逻辑运算符是用来进行布尔值运算的运算符,其返回值也是布尔值。
- 逻辑与 &&
两边都是 true才返回 true,否则返回 false
console.log(true && false) //false;
Console.log(3>2 && 1>2); //false
- 逻辑或 ||
只要一边为true既返回 true,两边都为false时返回false
console.log(true || false) //true;
Console.log(3>2 || 1>2); //true
- 逻辑非 !
逻辑非(!)也叫作取反符,用来取一个布尔值相反的值,如 true 的相反值是 false
var isOk = !true;
console.log(isOk); // false
- 短路运算(逻辑中断)
短路运算的原理:当有多个表达式(值)时,左边的表达式值可以确定结果时,就不再继续运算右边的表达式的值;
console.log( 123 && 456 ); // 456
console.log( 0 && 456 ); // 0
console.log( 123 && 456&& 789 ); // 789
console.log( 123 || 456 ); // 123
console.log( 0 || 456 ); // 456
console.log( 123 || 456 || 789 ); // 123
5:赋值运算符
= 直接赋值
var realname=”小明”;
+=,-=,*=,/=,%= 先计算在赋值;
举例:
var age = 10; age+=5;//15
var age = 10; age-=5;//5
var age = 10; age*=5;//50
var age = 10; age/=5;//2
var age = 10; age%=5;//0
6:运算符优先级
1:小括号 | () |
2:一元运算符 | ++、--、! |
3:算数运算符 | 先*、/、% 后 +、- |
4:关系运算符 | >、>=、<、<= |
5:相等运算符 | ==、!= 、===、!== |
6:逻辑运算符 | 先&& 后 || |
7:赋值运算符 | = |
8:逗号运算符 | , |
7:流程控制
定义:就是来控制代码按照一定结构顺序来执行,流程结构主要分三种:顺序结构、分支结构、循环结构。
顺序机构
最基本的流程控制,它没有特定的语法结构,程序会按照代码的先后顺序执行。
分支结构
由上到下执行代码的过程中,根据不同的条件,执行不同的路径代码,从而得到不同的结果。JS分支结构分为两种:if语句、switch语句。
- if语句
If(条件表达式){
// 条件成立执行的代码
}
If(条件表达式){
// 如果条件成立执行代码
}else{
// 条件不成立 执行此代码
}
// 适合于检查多重条件。
if (条件表达式1) {
执行代码1;
} else if (条件表达式2) {
执行代码2;
} else if (条件表达式3) {
执行代码3;
} else {
// 上述条件都不成立执行此处代码
}
- switch语句
switch(表达式) {
case n:
代码块
break;
case n:
代码块
break;
default:
默认代码块
}
举例:
var sex=1;
switch (sex){
case 1:
console.log("您喜欢的是猫");
break;
case "狗":
console.log("您喜欢的是狗");
break;
default:
console.log("其他动物");
}
总结:
- 我们开发里面 表达式我们经常写成变量
- 我们num 的值 和 case 里面的值必须是全等
- break 如果当前的case里面没有break 就会继续执行下一个case
8:三元表达式
语法结构: 表达式1 ? 表达式2 : 表达式3;
举例:
Var num=11;
var res = num >10 ? '是的' : '不是的';
Console.log(res); //不是的
四:循环
for循环
语法结构:
for(初始化变量;条件表达式;操作表达式){
//循环体
}
举例:
for (var i = 1; i <= 5; i++) {
console.log('数字为:' + i + '\n');
}
- 初始化变量 初始化一个计数器,用var声明新的变量,这个变量帮我们记录次数。
- 条件表达式 用于执行循环的条件,满足继续执行,不满足退出。
- 操作表达式 主要更新循环变量,在循环体结束后执行。
断点调试
断点调试:在程序的某一行设置一个断点,调试时,程序运行到这一行就会停住,然后你可以一步一步往下调试,调试过程中可以看各个变量当前的值,出错的话,调试到出错的代码行即显示错误,停下。断点调试可以帮助观察程序的运行过程。
断点调试的流程:
1、浏览器中按 F12--> sources -->找到需要调试的文件-->在程序的某一行设置断点
2、Watch: 监视,通过watch添加变量可以监视变量的值的变化。
3、摁下F11,程序单步执行,让程序一行一行的执行,观察watch中变量的值的变化。
for循环嵌套
定义:在循环语句中在定义一个循环语句的语法结构。
for (外循环的初始; 外循环的条件; 外循环的操作表达式) {
for (内循环的初始; 内循环的条件; 内循环的操作表达式) {
//需执行的代码;
}
}
举例:
var star = '';
for (var j = 1; j <= 5; j++) {
for (var i = 1; i <= 5; i++) {
star += '*'
}
// 每次满 5个*就加一次换行
star += '\n'
}
console.log(star);
总结:
- 外层循环执行一次,内层循环要执行全部次数。
- for循环是循环条件和数字直接相关的循环。
while循环
语法结构:
while (条件表达式) {
// 循环体代码
}
举例:
var num = 1;
while (num <= 10) {
console.log(num + '\n');
num++;
}
- 条件表达式为true,则执行循环体代码,否则退出循环。
- 循环代码执行完结束后,会继续执行条件表达式,它必须有条件否则会出现死循环。
do {
// 循环体代码 - 条件表达式为 true 时重复执行循环体代码
} while(条件表达式);
举例:
do{
var msg= prompt('密码:123456'); //输入密码为123456后循环体结束
}while(msg!=”123456”);
alert(“密码正确”);
- 与while循环方式一致,区别在于它先执行下循环体条件,在判断表达式。
- 循环体至少会执行一次。
continue、break
continue :关键字用于立即跳出本次循环,继续下一次循环。
for (var i = 1; i <= 5; i++) {
if (i == 3) {
continue; // 跳出本次循环,跳出的是第3次循环
}
console.log('提示信息:' + i + “\n”);
}
break 关键字用于立即跳出整个循环(循环结束)。
for (var i = 1; i <= 5; i++) {
if (i == 3) {
break; // 跳出整个循环。
}
console.log('提示信息:' + i + “\n”);
}
五:数组
数组的概念
- 数组是一种特殊的变量,它能够一次存放一个以上的值。
- 在数组中可以存放任意类型的元素。
数组的创建
- 通过 new 关键词创建数组
var 数组名 = new Array() ;
var arr = new Array(); // 创建一个新的空数组 “A”为大写
var arr = new Array(‘汽车’,’卡车’);
- 通过数组文本直接创建数组
var array-name = [item1, item2, ...];
var arr = [‘汽车’,’卡车’];
注意:在数组种可以存放任意数据类型。如:['小明',12,true,28.9]
数组的获取
数组可以通过索引(下标)来访问、设置、修改对应的数组元素,可以通过“数组名[索引]”的形式来获取数组中的元素,数组的下标是从0开始。
// 定义数组
var arr= [1,2,3];
// 获取数组中的第2个元素
alert(arr[0]); //1
alert(arr[1]); //2
alert(arr[2]); //3
alert(arr[3]); //undefined
注意:如果访问时数组没有和索引值对应的元素,则得到的值是undefined
数组的遍历
把数组中的每个元素都访问一次,可以通过for循环遍历数组。
var arr = ['小明','小红', '大胖'];
for(var i = 0; i < arr.length; i++){
console.log(arr [i]);
}
- length的长度是为数组的个数,非下标。
- 当我们数组里面的元素个数发生了变化,这个 length 属性跟着一起变化
- 数组的length属性可以被修改:
- 如果设置的length属性值大于数组的元素个数,则会在数组末尾出现空元素,访问空元素时显示undefined;
- 如果设置的length属性值小于数组的元素个数,则会把超过该值的数组元素删除
//js
var arr = ['小明', '小红', '小兰', '大胖'];
arr.length = 3;
console.log(arr.length);
console.log(arr);
数组添加元素
//js
数组[ 数组.length ] = 新数据;
//```
举例:
var arr = ['小明', '小红', '小兰', '大胖'];
arr[1] = '小帅';// 重新赋值
arr[arr.length] = '小帅';//末尾新增一个值
console.log(arr);
六:函数
函数:就是**封装了一段可被重复调用执行的代码块**。通过此代码块可以**实现大量代码的重复使用**。
// 声明函数
function 函数名(){
return 需要返回的值;
}
//举例
function sayHello(){
console.log(“hello”);
}
- function 是声明函数的关键字,必须小写
- 由于函数一般是为了实现某个功能才定义的, 所以通常我们将函数名命名为动词,比如 getSum;
- 函数需要调用后才执行,不调用里面代码块不执行。
函数的调用
// 声明函数 计算1-100之间的和
function getSum(){
var sumNum = 0;// 准备一个变量,保存数字和
for (var i = 1; i <= 100; i++) {
sumNum += i;// 把每个数值 都累加 到变量中
}
alert(sumNum);
}
getSum(); //函数调用。
函数的参数
- 形参:函数定义时设置接收调用时传入
- 实参:函数调用时传入小括号内的真实数据
参数的作用 : 在函数内部某些值不能固定,我们可以通过参数在调用函数时传递不同的值进去。
function say(mylanguage){
console.log(“请说” + mylanguage);
}
say(“中文”);
// 带参数的函数声明
function 函数名(形参1, 形参2 , 形参3...) { // 可以定义任意多的参数,用逗号分隔
// 函数体
}
// 带参数的函数调用
函数名(实参1, 实参2, 实参3...);
```
1. 调用的时候实参值是传递给形参的
2. 形参简单理解为:不用声明的变量
3. 实参和形参的多个参数之间用逗号(,)分隔
function getSum(sum1,sum2,sum3){
console.log(sum1);
console.log(sum2);
console.log(sum3);
}
getSum(sum1,sum2,sum3);
总结:
- 声明函数的时候可以不带参数;
- 实参多于形参时,形参只读取形参的个数;
- 实参少于形参时,形参未赋值undefined,为了确保不可避免错误,传参需一致。
函数的返回值
返回值:函数调用整体代表的数据;函数执行完成后可以通过return语句将指定数据返回。
// 声明函数
function 函数名(){
...
return 需要返回的值;
}
//举例
function getName(){
return “小二班的:张三”;
}
var myname = getName();
console.log(myname);
- 在使用 return 语句时,函数会停止执行,并返回指定的值
- 如果函数没有 return ,返回的值是 undefined
- return只返回一个值,如return 1,2。//返回2
break ,continue ,return
- break :结束当前的循环体(如 for、while)
- continue :跳出本次循环,继续执行下次循环(如 for、while)
- return :不仅可以退出循环,还能够返回 return 语句中的值,同时还可以结束当前的函数体内的代码
arguments的使用
当不确定有多少个参数传递的时候,可以用 arguments 来获取。JavaScript 中,
arguments实际上它是当前函数的一个内置对象。所有函数都内置了一个 arguments 对象,
arguments 对象中存储了传递的所有实参。arguments展示形式是一个伪数组,
因此可以进行遍历。伪数组具有以下特点:
- 具有 length 属性
- 按索引方式储存数据
- 不具有数组的 push , pop 等方法
function fn() {
// 我们可以按照数组的方式遍历arguments
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
fn(1, 2, 3);
fn(1, 2, 3, 4, 5);
注意:在函数内部使用该对象,用此对象获取函数调用时传的实参。
- 伪数组 并不是真正意义上的数组
- 具有数组的 length 属性
- 按照索引的方式进行存储的
- 它没有真正数组的一些方法 pop() push() 等等
七:作用域
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
JavaScript(es6前)中的作用域有两种:
- 全局作用域
- 局部作用域(函数作用域)
全局作用域
作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件。
//js
var num = 10;//全局作用域
局部作用域
作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,所以也称为函数作用域。
//js
function getnum(){ var num=20;}
JS没有块级作用域
在其他编程语言中(如 java、c#等),在 if 语句、循环语句中创建的变量,仅仅只能在本 if 语句、本循环语句中使用,如下面的Java代码:
java有块级作用域:
```java
if(true){
int num = 123;
system.out.print(num); // 123
}
system.out.print(num); // 报错
Js 代码:
if(true){
var num = 123;
console.log(num); //123
}
console.log(num ); //123
变量的作用域
在JavaScript中,根据作用域的不同,变量可以分为两种:全局变量,局部变量。
全局变量
在全局作用域下声明的变量叫做全局变量(在函数外部定义的变量)。
function fun() {
var num1 = 10; // num1就是局部变量 只能在函数内部使用
num2 = 20;
}
fun();
console.log(num2);//undefined
- 全局变量在代码的任何位置都可以使用
- 在全局作用域下 var 声明的变量 是全局变量
- 特殊情况下,在函数内不使用 var 声明的变量也是全局变量(不建议使用)
局部变量
在局部作用域下声明的变量叫做局部变量(在函数内部定义的变量)
- 局部变量只能在该函数内部使用
- 在函数内部 var 声明的变量是局部变量
- 函数的形参实际上就是局部变量
总结:
全局变量:在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存
局部变量:只在函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块运行结束后,就会被销毁,因此更节省内存空间
作用域链
- 只要是代码都一个作用域中,写在函数内部的局部作用域,未写在任何函数内部即在全局作用域中;
- 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域;
- 根据在**[内部函数可以访问外部函数变量]**的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
var num = 10;
function fn() { // 外部函数
var num = 20;
function fun() { // 内部函数
console.log(num);//20
}
fun();
}
fn();
总结:作用域链采取就近原则的方式来查找变量最终的值。
预解析
预解析的概念
- js引擎会把js 里面所有的var 还有function 提升到当前作用域的最前面。
- function 声明的变量在内存中进行提前声明或者定义。
- 代码执行: 从上到下执行JS语句。
变量预解析
变量提升(变量预解析): 变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升。
console.log(num); //直接打印变量未声明
console.log(num); // undefined 变量声明未赋值
var num = 10;
// 相当于执行了以下代码
// var num;
// console.log(num);
// num = 10;
结果:undefined
注意:变量提升只提升声明,不提升赋值
函数预解析
函数提升: 函数的声明会被提升到当前作用域的最上面,但是不会调用函数。
fn();
function fn() {
console.log('打印');
}
结果:控制台打印字符串 --- ”打印“
注意:函数声明代表函数整体,所以函数提升后,函数名代表整个函数,但是函数并没有被调用!
函数表达式声明函数
函数表达式创建函数,会执行变量提升,此时接收函数的变量名无法正确的调用:
fn();
var fn = function() {
console.log('我被执行了吗');
}
结果:报错提示 ”fn is not a function";
解释:该段代码执行之前,会做变量声明提升,fn在提升之后的值是undefined;而fn调用是在fn被赋值为函数体之前,此时fn的值是undefined,所以无法正确调用。
总结:
- 我们js引擎运行js 分为两步: 预解析 代码执行
- 预解析 js引擎会把js 里面所有的 var 还有 function 提升到当前作用域的最前面
- 预解析分为 变量预解析(变量提升) 和 函数预解析(函数提升)
- 变量提升 就是把所有的变量声明提升到当前的作用域最前面 不提升赋值操作
- 函数提升 就是把所有的函数声明提升到当前作用域的最前面 不调用函数
八:对象
在 JavaScript 中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象。
- 属性:事物的特征,在对象中用属性来表示(常用名词)
- 方法:事物的行为,在对象中用方法来表示(常用动词)
为什么用对象
- 保存一个值时,可以使用变量,保存多个值(一组值)时,可以使用数组。
- 如果要保存一个人的完整信息呢?
- 例如,保存一个人的个人信息:
//数组
var arr = [‘张三’, ‘男', 128,174];
缺点是:数据只能通过索引值访问,开发者需要清晰的清除所有的数据的排行才能准确地获取数据。
而使用对象:
var obj = {
"name":"张三",
"sex":"男",
"age":128,
"height":154
}
创建对象
- 使用对象字面量创建对象:就是花括号 { } 里面包含了表达。
- 键:相当于属性名
- 值:相当于属性值,可以是任意类型的值(数字类型、字符串类型,函数类型等)
//js
var info= {
name : '小明',
age : 18,
sex : '男',
say: function(){
alert('大家好啊~');
}
};
总结:
- 里面的属性或者方法我们采取键值对的形式 键 属性名 : 值 属性值
- 多个属性或者方法中间用逗号隔开的
- 方法冒号后面跟的是一个匿名函数
- 属性加引号和不加引号使用是一样的,如果键是以数字开头必须加引号,且不能用”.”来调用需要用[]调用。
对象的使用
//js
console.log(info.name) // 调用名字属性
console.log(info['name']) // 调用名字属性
info.say(); //调用方法
- 调用对象的属性 我们采取 对象名.属性名 . 我们理解为 的
- 调用属性还有一种方法 对象名['属性名']
- 调用对象的方法 sayHi 对象名.方法名() 千万别忘记添加小括号
var num = 10;
var obj = {
age: 18,
fn: function() {
alert(“1”);
}
}
function fn() {
alert(“2”);
}
console.log(obj.age);
// console.log(age);
总结:
- 变量 单独声明并赋值 使用的时候直接写变量名 单独存在
- 属性 在对象里面的不需要声明的 使用的时候必须是 对象.属性
- 函数是单独声明 并且调用的 函数名() 单独存在的
- 方法 在对象里面 调用的时候 对象.方法()
new创建对象
利用 new Object 创建对象。
var obj = new Obect();//此时obj已经为对象
利用属性和方法来赋值对象:
obj .name = '小明';
obj .age = 18;
obj.sex = '男';
obj.sayHi = function(){
alert('大家好啊~');
}
总结:
- Object() :第一个字母大写
- new Object() :需要 new 关键字
- 使用的格式:对象.属性 = 值;
构造函数创建对象
- 构造函数:是一种特殊的函数,主要用来初始化对象,
- 即为对象成员变量赋初始值,它总与 new 运算符一起使用。
- 我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。
//js
function 构造函数名(形参1,形参2,形参3) {
this.属性名1 = 参数1;
this.属性名2 = 参数2;
this.属性名3 = 参数3;
this.方法名 = 函数体;
}
- 构造函数的调用格式
var obj = new 构造函数名(实参1,实参2,实参3)
以上代码中,obj即接收到构造函数创建出来的对象。
举例:
// new 构造函数名();
function student(uname, age, sex) {
this.name = uname;
this.age = age;
this.sex = sex;
this.sing = function(sang) {
console.log(sang);
}
}
var info = new student('小明', 18, '男'); // 调用函数返回的是一个对象
为什么使用构造函数?
- 为什么使用构造函数:就是因我们前面两种创建对象的方式一次只能创建一个对象
- 因为我们一次创建一个对象,里面很多的属性和方法是大量相同的 我们只能复制
- 因此我们可以利用函数的方法 重复这些相同的代码 我们就把这个函数称为 构造函数
- 构造函数 就是把我们对象里面一些相同的属性和方法抽象出来封装到函数里面
写法总结:
- 构造函数名字首字母要大写
- 我们构造函数不需要return 就可以返回结果
- 我们调用构造函数 必须使用 new
- 我们只要new student() 调用函数就创建一个对象 info {}
- 我们的属性和方法前面必须添加 this
new 关键词的作用
- 在构造函数代码开始执行之前,创建一个空对象;
- 修改this的指向,把this指向创建出来的空对象;
- 执行函数的代码
- 在函数完成之后,返回this---即创建出来的对象
遍历对象
语法:
for (变量 in 对象名字) {
// 在此执行代码
}
for (var k in obj) {
console.log(k); // 这里的 k 是属性名
console.log(obj[k]); // 这里的 obj[k] 是属性值
}
总结:
- for in 可以对 对象和数组进行遍历。
- 这个变量(属性也可称键)通常可以用k或者key更符合语义。
九:内置对象
JavaScript 中的对象分为3种:自定义对象 、内置对象、 浏览器对象
前面两种对象是JS 基础内容,属于 ECMAScript;
第三个浏览器对象属于 JS 独有的, JSAPI 讲解内置对象就是指 JS 语言自带的一些对象,
这些对象供开发者使用,并提供了一些常用的或是最基本而必要的功能(属性和方法),
内置对象最大的优点就是帮助我们快速开发。
JavaScript 提供了多个内置对象:Math、 Date 、Array、String等
Math对象
Math 对象不是构造函数,它具有数学常数和函数的属性和方法。跟数学相关的运算(求绝对值,取整、最大值等)可以使用 Math 中的成员。
Math.PI | 圆周率 |
Math.floor() | 向下取整 |
Math.ceil() | 向上取整 |
Math.round() | 四舍五入版 就近取整 注意 -3.5 结果是 -3 |
Math.abs() | 绝对值 |
Math.max()/Math.min() | 求最大和最小值 |
Math.random() | 获取范围在[0,1)内的随机值0包含,1不包含 |
// Math数学对象 不是一个构造函数 ,所以我们不需要new 来调用 而是直接使用里面的属性和方法即可
console.log(Math.PI); // 一个属性 圆周率
console.log(Math.max(1, 99, 3)); // 99
console.log(Math.max(-1, -10)); // -1
console.log(Math.max(1, 99, '中文')); // NaN
console.log(Math.max()); // -Infinity
console.log(Math.floor(1.6));//向下取整,1
console.log(Math.ceil(1.6));//向上取整,2
console.log(Math.round(3.1));//四舍五入,就近取整
var a = Math.abs(7.25); //7.25
var b = Math.abs(-7.25);//7.25
var c = Math.abs(null);//0
var d = Math.abs("Hello");//NaN
var e = Math.abs(2+3);//5
console.log( Math.floor(Math.random()*100 + 1));//1-100之间的随机数
日期对象
Date 对象和 Math 对象不一样,Date是一个构造函数,
所以使用时需要实例化后才能使用其中具体方法和属性。Date 实例用来处理日期和时间。
//js date实例化
var now = new Date();
//举例
var now = new Date('2019/5/1');
注意:如果创建实例时并未传入参数,则得到的日期对象是当前时间对应的日期对象
var now = new Date();
console.log(now.getFullYear());//获取当年
console.log(now.getMonth()+1);//注意返回的是0-11 获取当月
console.log(now.getDate());//获取当天日期
console.log(now.getDay());//获取星期几,周日是0
console.log(now.getHours());//获取当前小时
console.log(now.getMinutes());//获取当前分钟
console.log(now.getSeconds())//获取当前秒
获取总毫秒数
基于1970年1月1日(世界标准时间)起的毫秒数
//第一种方法
console.log(now.valueOf())
console.log(now.getTime())
// 2. 简单写可以这么做
var now = + new Date();
// 3. HTML5中提供的方法,有兼容性问题
var now = Date.now();
数组对象
var arr = new Array();
- 如果只传入一个参数,则参数规定了数组的长度
- 如果传入了多个参数,则参数称为数组的元素
- 如果不传参数就是空数组
判断是否为数组
- instanceof 运算符
可以判断一个对象是否是某个构造函数的实例。
var arr = [1, 23];
var obj = {};
console.log(arr instanceof Array); // true
console.log(obj instanceof Array); // false
Array.isArray()
用于判断一个对象是否为数组,isArray() 是 HTML5 中提供的方法。
var arr = [1, 23];
var obj = {};
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false
push添加
push(值1,值2.....)末尾添加一个或多个值
var arr = [1, 23];
console.log("返回长度:" + arr.push(5,6,7));
console.log(arr);
pop删除
pop()删除数组最后一个值
console.log("返回值:" + arr.pop());
console.log(arr);
注意:无需删除参数,长度减1,返回被删除的值。
unshift添加
unshift(值1,值2,值3)在数开头添加一个或多个值。
console.log("返回值:" + arr.unshift(5,6,7)); //返回长度
console.log(arr);
shift删除
shift()删除数组第一个值
console.log("返回值:" + arr.shift());
console.log(arr);
注意:无需删除参数,长度减1,返回被删除的值。
数组排序
reverse() 颠倒数组中的顺序,无参数
var arr = [12, 23,3,7,8];
console.log(arr.reverse()); //返回新数组,会改变原来的数组
sort() 对数组进行排序,默认按字符串升序,原数组会改变。
var arr = [9, 1,3,7,8];
console.log(arr.sort()); //返回新数组,会改变原来的数组
console.log(arr);
console.log(arr.sort(function(a,b){
return a - b; //则为升序
}));
console.log(arr.sort(function(a,b){
return b-a; //则为降序
}));
默认排序顺序为按字母升序。
注意:
- 当数字是按字母顺序排列时"40"将排在"5"前面。
- 如果传入“function(a,b){ return a-b;}”,则为升序
- 如果传入“function(a,b){ return b-a;}”,则为降序
数组索引
indexOf(item,start) 可返回数组中某个值指定的元素位置。存在就返回,不存在返回-1;
lastIndexOf(item,start) 在数组中某个值指定的元素位最后一个索引,不存在返回-1;
item:代表要查找的元素值。
start:要查找元素的位置,indexof缺省从第一个开始找,lastinfexof从最后一个开始找。
举例:
var arr = [17, 11,3,7,8,3];
console.log(arr.indexOf(3));//2
console.log(arr.indexOf(3,3));//5//前3位之后,第一个3
console.log(arr.lastIndexOf(3));//5//前3位之后,第一个3
console.log(arr.lastIndexOf(3,3));//2//前3位置之内,最后一个3
数组连接
concat() 连接两个或多个数组 不影响原数组 返回一个新的数组
举例:
var arr = [1, 2,3];
var arr2 = [4,5,6];
var arr3 = [];
console.log(arr3 = arr.concat(arr,arr2));//123456
console.log(arr);//123
console.log(arr3);123456
数组截取
slice() 数组截取slice(start,end) 返回被截取项目的新数组,不改变原数组
start:从何处开始截取,如果是负值就从倒数第几个位置开始。
end:规定从何处开始结束选取,如果没有参数就是start到结束,如果为负数,就表示倒数第几个元素结束截取。(不包含最后一个元素)
var arr = [1, 2,3,4,5,6];
var arr3;
console.log(arr3 = arr.slice(0,2));//1,2
数组删除
splice(index, howmany, item1, ....., itemX) 数组删除,返回新数组,影响原数组
Index:从什么位置添加/删除项目。
Howmany:要删除的项目数。
item1...:要添加的项目值。
var info = ["Banana", "Orange", "Apple", "Mango"];
info.splice(1,1,"小红","小帅");//Orange被删除
console.log(info);//添加了 "小红","小帅"两个值
字符串对象
基本包装类型就是把简单数据类型包装成为复杂数据类型,这样基本数据类型就有了属性和方法。
var str = 'andy';
console.log(str.length);
按理基本数据类型是没有属性和方法的,js会把简单类型变为复杂类型。执行过程如下:
var temp = new String('andy');
// 2. 赋值给我们声明的字符变量
str = temp;
// 3. 销毁临时变量
temp = null;
字符串的不可变
指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。
当重新给字符串变量赋值的时候,变量之前保存的字符串不会被修改,
依然在内存中重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变。
由于字符串的不可变,在**大量拼接字符串**的时候会有效率问题
indexOf
返回指定内容在在字符串中的位置,如果找不到就返回-1,找到返回索引。
var info = "Banana";
console.log(info.indexOf("a"));//1
lastIndexOf
从后往前面找指定字符串中的位置,指返回第一个。
var info = "Banana";
console.log(info.lastIndexOf("a"));//5
根据位置返回字符
charAt(index) 返回指定位置的字符,index是索引号。
var info = "Banana";
console.log(info.charAt(0));//B
charCodeAt(index) 获得指定位置的字符的ASCII码
var info = "Banana";
console.log(info.charCodeAt(0));//66
str[index] 与charAt 使用等效
var info = "Banana";
console.log(info[0]);//B
字符串连接
concat(str1,str2,str3) 方法用于连接两个或多个字符串。等效于+;
var str1="123",str2="456",str3="789";
console.log(str1.concat(str2));//123456
console.log(str2.concat(str1,str3));//456123789
截取字符串
substr(start,length) 从start位置(索引)如果是负数从倒数第几个开始,length是个数。
var str1="路漫漫其修远兮";
console.log(str1.substr(0,2));//路漫
console.log(str1.substr(-1,1));//兮
slice(strat,end) 从start位置(索引)开始,截取到end位置(索引),end不包括。
var str1="路漫漫其修远兮";
console.log(str1.slice(0,1));//路
console.log(str1.slice(-5,-1));//漫其修远
注意:
start如果是负数表示从尾部截取多少个字符串,slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。
end 参数如果为负数,-1 指字符串的最后一个字符的位置,-2 指倒数第二个字符。
substring(start,end)
从start位置开始,截取到end位置,end取不到,基本与slic相同,但是不接受负数
var str1="路漫漫其修远兮";
console.log(str1.substring(0,1));//路
字符串替换
replace() 方法用于在字符串中用一些字符替换另一些字符,返回新字符串。
//语法
//字符串.replace(被替换的字符串,要替换的字符串);
var str="1,2,3";
console.log(str.replace(",","*")); //'1*2,3'
console.log(str.replace(/,/g,"*"));//正则替换全部的* 1*2*3
总结:
默认找到第一个匹配的值进行替换,正则的方式替换全部。/g替换全部,/t替换一个
字符串分割
split()方法用于切分字符串,它可以将字符串切分为数组,返回的是一个新数组。
//语法
//字符串.split(“分割字符”);
var str="1,2,3";
console.log(str.split(",")); //返回成数组
数据类型总结
简单数据类型
基本数据类型、值类型:在存储时变量中存储的是值本身,包括string ,number,boolean,undefined,null
简单类型传参:
函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的
形参时,其实是把变量在栈空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量。
function fn(a) {
a++;
console.log(a);//11
}
var x = 10;
fn(x);
console.log(x);//10
复杂数据类型
在存储时变量中存储的仅仅是地址(引用),通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等;
复杂类型传参:
函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。
function Person(name) {
this.name = name;
}
function f1(x) { // x = p
console.log(x.name); //刘德华
x.name = "张学友";
console.log(x.name); // 张学友
}
var p = new Person("刘德华");
console.log(p.name); // 刘德华
f1(p);
console.log(p.name); //张学友