JavaScript基础(1)

180 阅读15分钟

前端三层

  • HTML 结构层 从语义的角度描述页面结构
  • CSS 样式层 从美观的角度描述页面样式
  • JavaScript 行为层 从交互的角度描述页面行为

JavaScript是什么

JavaScript是一种运行在客户端的脚本语言,最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页增加动态功能。
浏览器就是一种运行JavaScript脚本语言的客户端,JavaScript的解释器被称为JavaScript引擎,为浏览器的一部分。

JavaScript的应用场景

JavaScript发展到现在几乎无所不能,常见的应用场景有:

  • 1.网页特效
  • 2.服务端开发(Node.js)
  • 3.命令行工具(Node.js)
  • 4.桌面程序(Electron)
  • 5.App(Cordova)
  • 6.控制硬件·物联网(Ruff)
  • 7,游戏开发(cocos2d-js) 等等

JavaScript的组成

JavaScript是由ECMAScript,DOM和BOM三者组成的。DOM和BOM是在ECMAScript基础上进行的功能扩展。

ECMAScript标准

  • JavaScript,JScript,ActionScript等脚本语言都是基于ECMAScript标准实现的。
  • 在JavaScript,JScript和ActionScript中声明变量,操作数组等语法完全一样,因为它们都是ECMAScript。但是在操作浏览器对象等方面又有各自独特的方法,这些都是各自语言的扩展。

DOM

DOM是文档对象模型的简称,方便我们对html文档进行操作。它会将整个html看做一个文档模型,元素间的嵌套关系构成了文档树结构,使用该模型的文档树结构,我们就可以对整个html节点和内容进行一系列的操作。

BOM

BOM是浏览器对象模型的简称,集成了一系列操作浏览器功能的API,方便我们操作浏览器窗口。比如页面跳转,弹出对话框,获取屏幕分辨率等等。

JavaScript的书写语法

书写位置

  • 写在行内
<input type="button" value="按钮" onclick="alert ('Hello world')" />
  • 写在html中的<script>标签中,常用
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script>
    alert("Hello world");
  </script>
</head>
  • 写在外部js文件中,在页面引入
<script src="main.js"></script>

注意:引用外部js文件的<script>标签中不可书写JavaScript代码,自定义的JavaScript代码需要书写在另一个新的<script>标签中。

JavaScript注释语法

  • 单行注释,使用//注释
 <script>
    //这是一个单行注释
  </script>
  • 块级(多行)注释,使用 /* */注释
<script>
   /*
     这是一个块级注释,
     这是一个块级注释,
     这是一个块级注释。
   */
 </script>

alert语句

alert是警示警告的意思,该函数(方法)作用是在浏览器中弹出一个警示框。

<script>
  alert("Hello world");//弹窗Hello world
</script>

prompt语句

prompt是提示的意思,该函数(方法)作用是弹出一个提示对话框,内部有一个提示语句和一个输入框,可以在输入框中根据提示任意输入内容。

<script>
  prompt("请输入您的年龄", "");//第一个参数是提示语,第二个参数是默认值
</script>

console控制台

在大部分浏览器中,右键点击审查元素(检查),都可以打开开发者模式,快捷键F12,其中有一个console(控制台)的选项面板,在js中有非常重要的作用。

  • 作用1:用于调试错误
  • 作用2:可以直接在控制台直接写一些js语句,进行执行
  • 作用3:js中有个内置对象console,内部封装了大量的属性和方法,可以通过调用这些方法执行我们想要输出的日志等内容。当我们进入控制台时就可以看到输出的内容了。
console.log("Hello world");
console.log("1", "2");
console.log(4 + 5);

数据类型

字面量

整数型

  • 十进制是最基本的数值字面量格式,可以直接在代码中输入。
  • 八进制字面值必须带前导0、0O、0o。八进制整数只能包括数字0-7。
  • 十六进制前缀是0x或0×。后面可以包含数字(0.9)和字母a-f或A-F。 在进行算术计算时或者参与程序,所有八进制和十六进制的数字都会被转换成十进制。

浮点数

  • 就是数学概念中的小数。
  • 包含:整数、小数点、小数部分。
  • 浮点数不区分进制,所有的浮点数都是十进制下的数字。
  • 注意:如果浮点数是大于0小于1的,可以省略小数点前面的0不写。

精度问题

浮点数值的最高精度是17位小数,但在进行算术计算时其精确度远远不如整数。
例如:0.1+0.2结果不是0.3,而是0.30000000000000004

console.log(1.2);
console.log(-1.2);
console.log(1.2e3);//表示1.2*10^3
console.log(1.2e-4);//表示1.2*10^4
console.log(0.1 + 0.2);//结果会是0.30000000000000004,这是js的精度问题

特殊数

Infinity无穷

  • Infinity:无穷的意思。首字母大写。
  • 由于计算机计算能力有限,如果高于最大计算值直接显示为正无穷Infinity,如果低于最小 计算值直接显示为-Infinity。
  • Infinity本身就是一个数字。 最小值:Number.MIN_VALUE,这个值为:5e-324
    最大值:Number.MAX_VALUE,这个值为:1.7976931348623157e+308
    无穷大:Infinity
    无穷小:-Infinity
console.log(Infinity);//正无穷
console.log(-Infinity);//负无穷

NAN

NaN: not a num表示不是一个正常的数,但是还是一个Number类型的数字。这个数字没办法用前面的表示方法表示。

  • NaN与任何值都不相等,包括他本身。
  • isNaN():判断一个数据是不是一个NaN。
console.log(0 / 0);//结果就是NaN
console.log(isNaN(0 / 0));

字符串

  • 字符串是由任意个数的有序或无序的字符组成的串,类似人类的语言,在JS中有自己特殊的与法。
  • 组成:字母、汉字、特殊符号、空白等。
  • 字符串字面量写法:是用一对单引号('')或双引号("")及引号内的字符构成、引号中间的字符可以有任意多个,也可以是没有字符的空字符串。
  • 注意:字符串中如果字符包含了双引号,则其外部应该由单引号标示,反之相同。

转义字符

使用反斜杠 \ 实现显示特殊字符。

console.log("1");//显示字符串1
console.log("'2'");//显示字符串'2'
console.log("\"2\"");//显示字符串"2"
console.log("C:\\test");//显示路径字符串C:\test

变量声明及赋值

使用var关键字声明

  • 规则(必须遵守的,不遵守会报错): 由字母、数字、下划线、$符号组成,不能以数字开头。 字母区分大小写,A和a示不同。 不能是关键字和保留字,关键字指的是js中有特殊功能的小词语,比如var、for等; 保留字指的是现在没有特殊功能,但是将来新语法中有可能作为关键字使用。
  • 规范(建议遵守的,不遵守不会报错): 变量名必须有意义 遵守驼峰命名法。多个单词组合而成的,第一个单词首字母小写,后面单词的首字母需要大写。 例如:userName、userPassword。

使用 = 符号赋值

变量定义之后,初始时没有进行賦值,内部有一个默认存储的值叫undefined〈未定义), 表示变量内部未赋值,可以存储数据了。

var userName;// 声明变量userName, 默认值是undefined
userName = "Jack";// 将字符串"Jack"赋值给变量userName
var userName2 = "Rose";// 声明变量userName2并赋值为"Rose"字符串
var a = 1,
b = 2,
c = 3;//一个var关键字声明多个变量并赋值

简单数据类型


null类型
null本身是个空对象指针,如果声明的变量将来用来存储对象,最好将该变量初始化为null

复杂数据类型


typeof()检测数据类型

console.log(typeof(1));
console.log(typeof("1"));
console.log(typeof(undefined));
console.log(typeof(true));
console.log(typeof(null));

变量的数据类型

JavaScript语言是一门动态类型的语言,变量并没有一个单独的数据类型,而是会随着内部存储数据的变化,数据类型也会发生变化。

  • 变量的数据类型,与内部存储数据有关。
  • 将来使用变量时,需要知道内部存储的数据是什么类型,避免程序出错。
var a = 1
console.log(typeof(a));//显示为number类型
a = "Hello"
console.log(typeof(a));//显示为string类型

数据类型转换

转换成字符串类型

  • .toString()方法
console.log(true.toString());//将bool类型的true转换成字符串true
var a = 1;
console.log(a.toString());//将number类型的1转换成字符串1
  • String()方法。有些值没有toString()方法,这个时候可以使用String()。比如:undefined和null
console.log(String(1));
console.log(String(undefined));
console.log(String(null));
  • +号拼接字符串方式。num+"",当+两边一个操作符是字符串类型,一个操作符是其它类型的时候,会先把其它类型转换成字符串再进行字符串拼接,返回字符串。
console.log(String(1 + "是唯一,The One"));

转换成数字类型

  • Number()方法
console.log(Number("123"));//显示数字123
console.log(Number(""));//显示数字0
console.log(Number("  "));//显示数字0
console.log(Number(true));//显示数字1
console.log(Number(false));//显示数字0
console.log(Number(undefined));//显示NaN
console.log(Number(null));//显示数字0
  • parseInt()方法 字符串转整数的方法。
    作用:第一,对浮点数进行取整操作;第二,将字符串转为整数数字。
  • 对数字取整功能,直接舍弃小数部分,只保留整数。
  • 字符串中,必须是纯数字字符串或者数字字符开头的字符串,才能转换为正常数字,且只取整数部分,如果不是数字打头的字符串,会转换为NaN
console.log(parseInt(123.34));//显示数字123
console.log(parseInt("123"));//显示数字123
console.log(parseInt("123.34"));//显示数字123
console.log(parseInt("123abc"));//显示数字123
console.log(parseInt("a123"));//显示NaN
console.log(parseInt(""));//显示NaN
  • parseFloat()方法 字符串转浮点数的方法。
    作用:将字符串转为浮点数数字。
    要求:满足浮点数数字字符必须在字符串开始,如果不在开始返回值都是NaN。

应用

转换成bool类型

  • Boolean()方法 Boolean()可以用于任何数据类型,将其他数据类型转为布尔类型的值。
    转为false:NaN、0、""空字符串、null、undefined 转为true:非0非NaN数字、非空字符串

运算符

算术运算符

有特殊值字面量参与的运算:

  • NaN参与的运算:得到的结果都是NaN
  • lnfinity参与的运算,视情况而定。 工作中并不会使用特殊值运算,没有实际应用的意义,但是要了解,以防面试遇到。 隐式转换在进行数字运算时结果和使用Number()方法转换结果一样。
// 字符串参与
console.log(1 + "2");
console.log(1 - "2");
console.log(1 * "2");
console.log(1 / "2");
console.log(1 % "2");
console.log(1 - "");
console.log(1 - "   ");
console.log(1 - "12abc");

// 其他数据类型参与
console.log(1 + true);
console.log(1 + false);
console.log(1 + undefined);
console.log(1 + null);

比较运算符

也叫关系运算符。运算结果是true或false。

特殊值参与比较运算:

  • NaN参与, 不等于和不全等于结果是true,其他的都得到false
  • lnfinity参与的运算,视情况而定 其他数据类型参与比较运算(排除字符串与字符串的比较):
  • 其他数据类型也会隐式转换为数字参与比较。 "123" → 123 | true → 1 | false → 0 | null → 0 | undefined → NaN | "0abc” → NaN
  • null的判断比较特殊:null与0判断时,相等判断为false,>=和<=判断为true
  • null==undefined结果为true,因为undefined派生于空指针,值上和null是相等的
console.log(1 == "1");// true
console.log(1 == true);// true
console.log(0 == false);// true
console.log(0 == "");//  true
console.log(0 == "     ");//  true
console.log(0 == undefined);// false
console.log(0 == null);// false
console.log(1 > null);// true
console.log(0 >= null);// true
console.log(0 <= null);// true
console.log(undefined == null);// true

字符串与字符串比较

console.log(6 < "12");// true
console.log("6" < "12");// false
console.log("A" < "12");// false
console.log("A" < "a");// true
console.log("banner" < "banana");// false

比较符运算顺序 从前往后比较,先得出前面的比较结果,再将结果和后面进行比较。

console.log(3 > 2 > 1);// 先运算3>2 得到 true ,再运算 true > 1 得到最终结果false

逻辑运算符

除了布尔类型的值之外,其他数据类型的值也可以参与逻辑运算。运算过程中需要将操作数隐式转换为布尔类型的值,参与判断计算,最终运算结果还是原来的某个位置的数据。 所以,并不是所有逻辑运算返回结果都是布尔值,其他数据参与得到的就是数据本身。

console.log(null && "123");// 结果null
console.log(12 && "123");// 结果123
console.log(12 || "123");// 结果12
console.log(undefined || null);// 结果null
// 非运算的运算结果只能是 true 或false
console.log(!9);// 结果是false

逻辑运算符运算顺序

  • 同种运算符从前往后运算。
  • 综合运算顺序:非、与、或。

赋值运算符

赋值运算符必须有变量参与运算,赋值运算符会做两件事情:

  • 第一,将变量中原始值参与对应数学运算,与右侧的数据。
  • 第二,将运算结果再重新赋值给变量。 变量位于操作符的左侧。
var a = 5;
a += 3;  // 等价于  a = a + 3
console.log(a);// 输出为8
a *= 6; // 等价于  a = a * 6
console.log(a);// 输出为48
// 递加
console.log(a++);// 先调用a输出为48,再运算a++得到a为49
console.log(++a);// 先运算++a得到a为50,输出为50
console.log(a);// 输出为50

一元运算符

// 定义变量
var a = 10,b = 20,c = 30;
// 计算一个综合的算式
var num = a++ + ++b + c++ + ++a;
console.log(num);// 转换成(a+(b+1)+c+(a+1)),输出73
console.log(a);// 输出12
console.log(b);// 输出21
console.log(c);// 输出31

运算优先级

流程控制语句

条件分支语句

if语句

// 案例:让用户输入自己的考试成绩,反馈给他是否及格的结果
var s = parseFloat(prompt("请输入您的成绩","67"));
// 判断:超过60分及格
if (s >= 60) {
  alert("恭喜你,你及格了");
} else {
  alert("很遗憾,你没有及格");
}

多分支if语句

var s = parseFloat(prompt("请输入您的成绩","67"));
if (s >= 85) {
  alert("优秀");
} else if (s >= 75)
  alert("良好");
} else if (s >= 60)
  alert("及格");
} else {
  alert("不及格");
}

if语句嵌套

// 用户输入
var sex = prompt("请输入您的性别","男");
var age = parseInt(prompt("请输入您的年龄","45"));
if (sex === "男") {
  // 男性,年龄需要大于60岁
  if (age >= 60) {
    alert("恭喜你,可以享受人生了")
  } else {
    alert("忍忍吧,还要坚持坚持");
  }
} else {
  // 女性,年龄需要大于55岁
  if (age >= 55) {
    alert("恭喜你,幸福人生开始了")
  } else {
    alert("太难了,还得继续坚持");
  }
}

三元表达式

虽然if语句可以模拟三元表达式,但是三元表达式有自己的优点:

  • 二选一的情况下,三元表达式结构更加筒单。
  • 三元表达式作为一个表达式参与程序时必须运算出结果才能参与,可以利用这个特点,将二选一结果赋值给一个变量。 所以,遇到给一个变量根据条件二选一赋值的情况,可以使用三元表达式。
// 给变量赋值,根据条件二选一时,使用三元表达式更简单
var a = 4;
var b = a >= 5 ? 1 : 0;//先判断条件a>=5得到false,那么表达式值为0
console.log(b);//输出0

switch语句

注意事项:

// 用户输入
var xingzuo = prompt("请输入您的星座","白羊座");
// 进行匹配
switch (xingzuo) {
  case "白羊座":
    alert("运势持续在线,将会是忙而充实的一天。");
    break;
  case "金牛座":
    alert("你或许需要付出更多的努力,才能实现自己的大志。");
    break;
  case "双子座":
    alert("你的脾气比较大,容易把负面情绪波及到最亲近的人。");
    break;
  case "巨蟹座":
    alert("人际关系会给你带来一些便利,善加把握会得到很多。");
    break;
  default:
    alert("对不起,数据库不全,不能找到您的星座");
    break;
}
// 案例2: 输出对应月份的天数
var month = parseInt(prompt("请输入一个月份的数字","1"));
// 输出对应的天数
switch (month) {
  case 1:
  case 3:
  case 5:
  case 7:
  case 8:
  case 10:
  case 12:
    alert("这个月有31天");
    break;
  case 2:
    alert("这个月有28天或29天");
    break;
  default:
    alert("这个月有30天");
}

条件分支语句总结

实际工作中使用三种语句的情景:

  • if语句:最常用的语句,所有的判断情况都能够书写。
  • 三元达式:多用于绐变量赋值根据条件二选一的情况。
  • switch语句:多用于给一个表达式去匹配多种固定值可能性的情况。

循环语句

for循环

应该掌握for循环运行的一个轨迹、路径,自己去推导for循环运行的过程, 这样就可以实现任意的for循环了。如下图,是按①→②→③→④→②……②→⑤顺序执行的。 注意:

  • 小括号内部必须有两个分号。
  • for循环{}后面不需要加分号。
  • 如果②位置语句不写,相当于没有设置入口条件,或者条件永远为真,没法限制什么时候停止循环了,出现死循环。
  • ③位置是循环的结构体,每次进入循环都要执行完后,才能执行语句④,③位置的语句是可以人为自定义的,甚至可以书写if语句。
  • for循环嵌套if语句:表示既要能执行循环,还要满足if语句的条件。
  • for循环嵌套for循环:外层循环执行一次,内层循环作为外层③位置的结构体,必须执行完所有的内层循环,才能进入外层循环下一次的④。
  • 循环内的变量是全局变量,必须避免循环嵌套时起相同的变量名,内层和外层变量名必须不同,常用的变量名i,j,k
// for 循环内部嵌套 for 循环
for (var i = 1 ; i <= 4 ; i++) {
  for (var j = 5; j <= 8 ; j++) {
    console.log(i,j);
  }
}

do while循环

先执行后判断条件。 注意:

  • 如果循环中需要循环变量参与,循环变量必须定义在循环外面,否则会被重置。如果将循环变量写在结构体内,i的初始值每次都会被重置,容易出现死循环。
  • 循环变量自加的过程需要写在{}循环体内部。变量自加过程写在输出语句前面和后面,结果是不同的。
  • dowhile循环即便条件第一次测试就为假,也会执行一次结构体。
// 输出1到10之间
var i = 1;
do {      
  i++;
  console.log(i);
} while (i <= 0);

while循环

// 输出1到10之间的数字
var i = 1;
while (i <= 10) {
  i++;
  console.log(i);
}

循环总结:

  • 遇到必须先执行一次结构体的循环,使用dowhile循环。
  • 先测试入口条件的循环,可以选择for循环或while循环。

break语句

  • break语句的作用可以立即停止当前(本层)的for、dowhile、while循环。
  • 根据一些条件设置break位置,直到循环能够执行到break语句立即停止执行,跳出循环。
// 找到一个这样的数字,就说明存在,所以不需要往后面继续验证
for (var i = 1 ; i <= 50 ;i++) {
  if (i % 5 == 0) {
    console.log(i);
    break;
  }
}
// 如果想终止外层循环,需要给外层循环添加一个名字
waiceng : for (var i = 1 ; i <= 4; i++) {
  for (var j = 1 ; j <= 4; j++) {
    console.log(i,j);
    // 补充打断条件
    if (j >= 2) {
      break waiceng;
    }
  }
}

continue语句

遇到continue表示当前的一次循环数据不是我们想要的,会立即停止当前次的循环,立即进入下一次循环。 注意:

  • 要根据特殊条件设置continue的位置。
  • continue如果没有特殊指示只能进入自己的下一次循环,不能立即停止外层循环的这一次进入下一次。
  • 控制外层循环的方式与break一样,都是添外层的标签名。
// 找到 1-30 之间不是 5 的倍数的数字进行输出
for (var i = 1 ; i <= 30 ; i++) {
  // 排除 5 的倍数
  if (i % 5 == 0) {
    // 说明是 5 的倍数,不要往下进行输出
    continue;
  }
  // 能够执行到这里,说明不是 5 的倍数
  console.log(i);
}
// continue 要控制外层循环,需要给外层循环添加标签名
waiceng : for (var i = 1 ; i <= 4; i++) {
  for (var j = 1 ; j <= 4; j++) {
    // 补充打断这一次条件
    if (j % 2 == 0) {
      continue waiceng;
    }
    console.log(i,j);
  }
}

总结: break和continue这两个语句的出现可以帮助我们大量的优化代码,减少了计算机的计算次数。

穷举思想

制作方法:

  • for循环:外层使用for循环进行一一列举。
  • if语句:内层用if语句进行判断,筛选需要的数据,如果满足条件就操作数据,如果不满足条件跳过看下一次循环的数据。

累加器

  • 有时候需要的不是每个数据是什么,需要得到所有数据的加和,必须想办法将所有的数据的和存起来,就用到了累加器。
  • 累加器本质就是变量。
  • 实现累加的效果,就是利用循环,每次循环就将新的数据加到原始的变量中去,赋值过程是一个加等于赋值。
// 求 1-10 之间所有数字的和
var n = 0;
// 循环累加所有的数字
for (var i = 1 ; i <= 10 ; i++) {
  // 将每一次的数据 i 要累加到 n 中去
  n += i;
  // console.log(n);
}
// 循环结束后就可以使用最终的累加结果
console.log(n);

注意:

  • 累加器必须定义在循环外面的前面,如果定义在循环内部,每次循环都会将累加器重置,不能实现累加
  • 累加器的初始值必须设置,而且必须设置为0,不会影响累加结果
  • 使用最终累加结果时,必须在for循环结束后的外面,如果写在循环内部,循环没结束,并不是最终需要的值。

累乘器

和累乘器十分相似。

// 求 10 的阶乘
// 累乘器,初始值必须是 1
var mul = 1;
for (var i = 10 ; i >= 1 ; i--) {
  mul *= i;
}
// 循环结束后使用累乘结果
console.log(mul);

注意:

  • 累乘器必须定义在循环外部前面。
  • 累乘器的初始值必须是1,1乘以任何数都等于本身。
  • 累乘器最终结果必须在for循环结束后使用。