五、前端开发语言体系-JavaScript基础
JavaScript基础
JavaScript是在网站浏览器上运行的是一门脚本语言:不需要编译,直接运行。主要是向使用HTML和CSS构建的网站添加,并起到实现各种页面动态效果的作用。
JavaScript可以做什么:
- 网页特效
- 服务端开发(Node.js)
- 命令行工具(Node.js)
- 桌面程序(Electron)
- App(Cordova)
- 控制硬件–物联网(Ruff)
- 游戏开发(cocos2d-js)
变量、值和类型
JavaScript 变量是存储数据值的容器。所有 JavaScript 变量必须以唯一的名称的标识。这些唯一的名称称为标识符。JavaScript 标识符对大小写敏感。
在 JavaScript 中创建变量被称为“声明”变量。我们可以通过 var 关键词来声明 JavaScript 变量。
声明之后,变量是没有值的(undefined)。如需赋值给变量,需要使用等号。
var carName; //声明变量
carName = 7; //给变量赋值
var newName = "porsche"; //声明时赋值
//一条语句声明多个变量,用逗号分隔
var person = "Bill Gates", carName = "porsche", price = 15000;
//声明可以横跨多行
var person = "Bill Gates",
carName = "porsche",
price = 15000;
有时候我们也用 let 关键字来声明变量。
- let 用来声明局部变量,非常适合声明块级作用域的变量。
- var定义的更像是一种全局变量,{ }花括号限定不了 var 声明变量的访问范围。
{
let i = 9; // i变量只在 花括号内有效!!!
}
console.log(i); // Uncaught ReferenceError: i is not defined
{
var i = 9;
}
console.log(i); // 9
JavaScript 变量能够保存多种数据类型:数值,字符串值,布尔值,数组,对象。
JavaScript不区分整数和浮点数,统一用Number表示。
- 12 // 整数
- 3.14 // 浮点数
- 1.1e3 // 科学计数法 1.1 x 1000
- -12 // 负数
- NaN // 表示Not a Number,无法计算结果时候使用
- Infinity // 无限大
字符串是以单引号’或双引号"括起来的任意文本。布尔值只有两个值:true 或 false,布尔值经常用在条件测试中。
var x1 = 34.00; // 浮点数
var x2 = 34; // 整数
var carName = "Porsche 911"; // 使用双引号
var carName = 'Porsche 911'; // 使用单引号
var x = true;
var y = false;
数组是一组按顺序排列的集合,集合的每个值称为元素。JavaScript的数组可以包括任意数据类型。
数组用[ ]表示,元素之间用逗号,分隔。数组的元素可以通过索引来访问。请注意,索引的起始值为 0。
var cars = ["Porsche", "Volvo", "BMW"];
var arr = [1, 2, 3.14, 'Hello', null, true]; //arr[0]=1
JavaScript的对象是一组由键-值组成的无序集合,用花括号{ }来书写。对象属性是 name : value 对,由逗号分隔。要获取一个对象的属性,我们用‘对象变量.属性名’的方式。
var person1 = {Name:"Bill", age:62, eyeColor:"blue"};
var person2 = {
name: 'Bob',
age: 20,
tags: ['js', 'web', 'mobile'],
city: 'Beijing',
hasCar: true,
zipcode: null
};
//person1.age = 62
//person2.name = 'Bob'
JavaScript 拥有动态类型。这意味着相同变量可用作不同类型。
var x; // 现在 x 是 undefined
x = 7; // 现在 x 是数值
x = "Bill"; // 现在 x 是字符串值
null表示一个“空”的值,它和 0 以及空字符串’‘不同,0 是一个数值,’'表示长度为 0 的字符串,而 null 表示“空”。
JavaScript的设计者希望用 null 表示一个空的值,而 undefined 表示值未定义。事实证明,这并没有什么卵用,区分两者的意义不大。大多数情况下,我们都应该用null。undefined仅仅在判断函数参数是否传递的情况下有用。
运算符和表达式
算术运算符 | 描述 | 赋值运算符 | 描述 | 比较运算符 | 描述 |
---|---|---|---|---|---|
+ | 加法 | = | 把值赋给变量 | == | 等于 |
- | 减法 | += | x+=y 等价于 x=x+y | === | 等值等类型 |
* | 乘法 | -= | x-=y 等价于 x=x-y | != | 不相等 |
/ | 除法 | *= | x *=y 等价于 x=x * y | > | 大于 |
% | 模 | /= | x/=y 等价于 x=x/y | < | 小于 |
++ | 递增 | %= | x%=y 等价于 x=x%y | ? | 三元运算符 |
– | 递减 |
在用于字符串时,+ 运算符被称为级联运算符,能够用于对字符串进行相加。同时,如果用数字和字符串相加,结果将是字符串!
str = "hello"
Str += "kity" //str = "hellokity"
x = 10
z = "hello"+x //z = "hello10"
逻辑运算符 | 描述 | 类型运算符 | 描述 |
---|---|---|---|
&& | 逻辑与 | typeof | 返回变量的类型 |
|| | 逻辑或 | instanceof | 返回 true,如果该对象是对象类型的实例 |
! | 逻辑非 |
typeof 运算符返回变量或表达式的类型。
- typeof 运算符把声明时未定义的变量返回 undefined
- typeof 运算符把对象、数组或 null 返回 object,函数返回 function
/*
typeof x 和 typeof(x) 等价
*/
typeof 7 // 返回 "number"
typeof "Bill" // 返回 "string"
typeof(2<3) // 返回 "boolean"
var x;
var y = null;
typeof(x) // 返回 "undefined"
typeof(y) // 返回 "object"
var a = [1, 2, 3]
var p = {
name:"bill",
age:22
};
typeof(a) // 返回 "object"
typeof(p) // 返回 "object"
表达式与数学中的定义相似,表达式是指具有一定的值、用操作符把常数和变量连接起来的代数式。一个表达式可以包含常数或变量。
在JavaScript中,常见的表达式有4种:
- 赋值表达式
- 算术表达式
- 布尔表达式
- 字符串表达式
表达式基本上都是结合着运算符一起使用的,学会了使用运算符,也就学会了使用表达式。
num = 10; //赋值表达式
num += 20; //算术表达式
if(2<3) //布尔表达式
txt = "hello" + "world" //字符串表达式
语句
在 HTML 中,JavaScript 语句是由 web 浏览器“执行”的“指令”。
JavaScript 语句由以下构成:值、运算符、表达式、关键词和注释。
JavaScript 语句以分号 ; 分割。分号不是必需的,但是请在每条可执行的语句之后添加分号来保证程序的可读性。
大多数 JavaScript 程序都包含许多 JavaScript 语句。这些语句会按照它们被编写的顺序逐一执行。
document.getElementById("demo").innerHTML = "Hello Kitty.";
//这条语句告诉浏览器在 id="demo" 的 HTML 元素中输出 "Hello Kitty.":
JavaScript 语句常常通过某个关键词来标识需要执行的 JavaScript 动作,其大部分关键字都与 C 语言一致。这里列出一些常用的特有关键字:
关键字 | 描述 |
---|---|
debugger | 停止执行 JavaScript,并调用调试函数(如果可用) |
function | 声明函数 |
try … catch | 对语句块实现错误处理 |
var | 声明变量 |
JavaScript 单行注释以 // 开头。多行注释以 /* 开头,以 */ 结尾。
数组
JavaScript 数组它能够一次存放一个以上的值,并且还可以通过引用索引号来访问这些值。
JavaScript数组是动态的,根据需要它们会增长或缩减,并且在创建数组时无需声明一个固定的大小或者在数组大小变化时无需重新分配空间。
创建数组的两种方法:
- 使用数组文本
- var array-name = [item1, item2, …];
- 使用关键词 new
- var array-name = new Array(item1, item2, …);
这两种方法完全等价,出于简洁、可读性和执行速度的考虑,建议使用数组文本方法。
var cars = ["Saab", "Volvo", "BMW"];
var cars = new Array("Saab", "Volvo", "BMW");
我们可以通过引用索引号(下标号)来引用某个数组元素。数组索引从 0 开始。[0] 是数组中的第一个元素。[1] 是第二个,以此类推。
同时,JavaScript 可通过引用数组名来访问完整数组。
var cars = ["Audi", "BMW", "porsche"];
document.getElementById("demo").innerHTML = cars[0]; //Audi
document.getElementById("demo").innerHTML = cars; //Audi,BMW,porsche
数组是一种特殊类型的对象,可以在相同数组中存放不同类型的变量。我们可以在数组保存对象,保存函数。甚至可以在数组中保存数组。
myArray[0] = {type:"Volvo", year:2016};
myArray[1] = myFunction;
myArray[2] = cars; //cars是刚才定义的数组
数组属性和常用方法:
- length 属性返回数组的长度
- toString() 把数组转换为数组值(逗号分隔)的字符串。
- join() 方法也可将所有数组元素结合为一个字符串。
- indexOf() 方法在数组中搜索元素值并返回其位置
- sort( ) 方法对数组进行排序
- reverse() 方法反转数组中的元素
- push( ) 方法向数组添加新元素
- pop() 方法从数组中删除最后一个元素,并返回该值
var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.length; //长度是 4
fruits.toString(); //Banana,Orange,Apple,Mango
fruits.join(" * "); //Banana * Orange * Apple * Mango
var a = fruits.indexOf("Apple"); //a的值为2
fruits.sort(); //Apple,Banana,Mango,Orange
fruits.reverse(); //Orange,Mango,Banana,Apple
fruits.pop(); // 从 fruits 删除最后一个元素("Mango")
fruits.push("Lemon"); // 向 fruits 添加一个新元素 (Lemon)
JavaScript 数组属于对象,typeof 运算符返回 “object”,我们使用两种方法来判断数组:
- 新方法 Array.isArray()
- 假如对象由给定的构造器创建,则 instanceof 运算符返回 true
var fruits = ["Banana", "Orange", "Apple", "Mango"];
Array.isArray(fruits); // 返回 true
fruits instanceof(Array); // 返回 true
函数和对象
JavaScript 函数是被设计为执行特定任务的代码块,函数会在某代码调用它时被执行。
JavaScript 函数通过 function 关键词进行定义,其后是函数名和括号 ( ),由函数执行的代码被放置在花括号中:{ }
function name(参数 1, 参数 2, 参数 3) { //参数是局部变量
要执行的代码
}
当 JavaScript 到达 return 语句,函数将停止执行。函数通常会计算出返回值。这个返回值会返回给调用者.
var x = myFunction(7, 8); // 调用函数,返回值被赋值给 x
document.getElementById("demo").innerHTML = x; //x=56
function myFunction(a, b) { // 函数返回 a 和 b 的乘积
return a * b;
}
JavaScript 对象中的值以‘名称 : 值对’的方式来书写,名称 : 值对被称为属性。
在对象上执行的动作称为方法,以函数定义被存储在属性中。方法是作为属性来存储的函数。在函数定义中,this 引用该函数的“拥有者”。
var person = {
firstName: "Bill", //属性
lastName : "Gates",
id : 678,
fullName : function() { //方法
return this.firstName + " " + this.lastName;
}
};
我们能够以两种方式访问属性:
- objectName.propertyName
- objectName[“propertyName”]
通过如下语法访问对象方法:
- objectName.methodName()
如果不用括号 ( ) 来访问方法,将返回函数定义。
person.lastName; //属性
person["lastName"]; //属性
name = person.fullName(); //方法
name = person.fullName; //返回函数定义
如果通过关键词 “new” 来声明 JavaScript 变量,则该变量会被创建为对象。
var x = new String(); // 把 x 声明为 String 对象
var y = new Number(); // 把 y 声明为 Number 对象
var z = new Boolean(); // 把 z 声明为 Boolean 对象
请避免字符串、数值或逻辑对象。他们会增加代码的复杂性并降低执行速度。
严格模式
严格模式使我们更容易编写“安全的” JavaScript,严格模式把之前可接受的“坏语法”转变为真实的错误。在严格模式中,向不可写的、只能读取的、不存在的属性赋值,或者向不存在的变量或对象赋值,将抛出错误。
例如,在普通的 JavaScript 中,错打变量名会创建新的全局变量。在严格模式中,此举将抛出错误,这样就不可能意外创建全局变量。
“use strict”; 定义 JavaScript 代码应该以“严格模式”执行。
“use strict” 指令只能在脚本或函数的开头被识别。
- 在脚本开头进行声明,拥有全局作用域(脚本中的所有代码均以严格模式来执行)
- 在函数中声明严格模式,拥有局部作用域(只有函数中的代码以严格模式执行)
"use strict"; //定义以“严格模式执行”执行
x = 3.14; //在不声明变量的情况下使用变量,是不允许的
var y = 3.14;
delete y; //删除变量(或对象、或函数)是不允许的
function x(p1, p1) {}; //重复参数名是不允许的
类
构造方法 constructor 是创建和初始化class创建对象的特殊方法,类似 Java、C# 的构造函数,只不过 Javascript 需要借助关键字 constructor。
一个类中只能有一个构造方法 constructor。当然,JavaScript类的构造方法是可选的,可以不写构造函数,这样 JavaScript 会声明一个默认的构造函数。
constructor(...args) { //基类构造函数
...
}
constructor(...args) { //派生类构造函数
super(...args);
...
}
Super 关键字用来调用父类的构造函数,也可以用来调用父对象上的函数。super 关键字至多出现一次,必须在使用 this 关键字之前使用。
super([ arguments ]); // 调用 父对象/父类 构造函数
super.functionOfParent([ arguments ]); // 调用 父对象/父类 上的方法
创建类有两种方式:类声明、类表达式。
类声明(class)
// extends是继承的语法,书写后 `子类 extends 父类`
class name [extends] {
// class body
}
示例:
class Human {
constructor(name, weight, height) {
this.name = name;
this.weight = weight;
this.height = height;
this.bmi = weight / height / height;
}
}
console.log('bmi: ' + new Human('匿旅', 71, 1.72).bmi);
// expected output: bmi: 23.99945916711736
类表达式
/**
* className 写的话只能在后面的类体内访问到,不写的话就是一个匿名
* exteds 继承父类
* 这个类可以理解为名字为 MyClass
*/
const MyClass = class [className] [extends] {
// class body
};
示例:
let World = class {
constructor() { }
bar () {
return 'Hello World!';
}
}
let instance = new World();
instance.bar(); // "Hello World!"
类声明必须有类名,类表达式可以没有类名。
Get 和 Set 函数:
- get函数,直接使用 实例对象.属性
- set函数,直接赋值 实例对象.属性 = xxxx
class Polygon {
constructor(height, width) {
this.name = 'Polygon';
this.height = height;
this.width = width;
}
}
class Square extends Polygon {
constructor(length) {
// 在这里, 它调用了父类的构造函数, 并将 length 提供给 Polygon 的"width"和"height"
super(length, length);
// 注意: 在派生类中, 必须先调用 super() 才能使用 "this"。
// 忽略这个,将会导致一个引用错误。
this.name = '正方形';
}
get area () {
return this.height * this.width;
}
set area(value) {
// 注意:不能使用 this.area = value 为area赋值
// 否则会导致循环call setter方法导致爆栈
this._area = value;
}
}