JavaScript基础知识(二)
- 一、ES2015 基础语法
- 1.变量
- 2.常量
- 3.模板字符串
- 4.结构赋值
- 二、函数进阶
- 1. 设置默认参数值
- 2. 立即执行函数
- 3. 闭包
- 4. 箭头函数
- 三、面向对象
- 1.面向对象概述
- 2.基本概念
- 3.新语法与旧语法
- 4.ES5 面向对象的知识
- 4.1 ES5构造函数
- 4.2 原型对象
- 4.3 原型链(继承)
- 5.ES6 面向对象的知识
- 5.1 Class关键字
- 5.2 继承
一、ES2015 基础语法
1.变量
使用 let 代替 var。
let 的优点:
- 块级作用域;
{
var str = 'hello world';
}
console.log(str); // hello world
{
let str = 'hello world';
}
console.log(str); // 报错:str is not defined
- 不存在变量提升;
console.log(str);
var str = 'hello world'; // undefined
console.log(str);
let str = 'hello world'; // 报错:Cannot access 'str' before initialization
- 不允许重复声明。
var num = 10;
var num = 20;
console.log(num); // 20
let num = 10;
let num = 20;
console.log(num); // 报错:Identifier 'num' has already been declared
总的来说,let 会让变量声明更加规范。
2.常量
使用 const 定义 常量(即不变的值)。
定义之后不可以修改:
const num = 10;
num = 20;
console.log(num); // 报错:Assignment to constant variable.
使用 const 声明的几种情况:
- 不变的值;
const PI = 3.14;
console.log(PI); // 3.14
- 函数表达式;
const fun = function (a, b) {
return a + b;
}
fun(1, 1);
- 对象;
function getStundent(){
return {
name: 'Lulu',
age: 20
}
}
// 对象声明可以使用常量
const student = getStundent();
// 虽然是常量,但是对象里面的属性可以改变
student.name = 'Mary';
console.log(student.name); // 'Mary'
- 引入外部模块。
const express = require('express');
3.模板字符串
语法:
// 反引号 ``
let str = `hello world`;
console.log(str); // hello world
优点:
- 支持换行:
let str = `hello
world`;
console.log(str);
- 支持嵌入变量,${} 连接字符串:
let year = "2023";
let month = "08";
let date = "08";
// 拼接成 "2023年08月08日"
let result = `${year}年${month}月${date}日`
console.log(result); // 2023年08月08日
4.结构赋值
- 数组的解构赋值:
// let n = 10;
// let m = 20;
let [n, m] = [10, 20];
console.log(n); // 10
console.log(m); // 20
示例:交换 n 和 m 的值。
let n = 10;
let m = 20;
// 交换
[n, m] = [m, n];
console.log(n); // 20
console.log(m); // 10
- 对象的结构赋值:
// let obj = {name: "xiaoming", age: 10};
// let name = obj.name;
// let age = obj.name;
let { name, age } = { name: "xiaoming", age: 10 };
// 如果颠倒 name,age的顺序并不会影响结果:
// let { age, name } = { name: "xiaoming", age: 10 };
console.log(name); // xiaoming
console.log(age); // 10
- 通过解构赋值传递参数:
// function getName(obj) {
// return obj.name
//}
function getName({name, age}) {
// name ==> obj.name
// age ==> obj.age
return name
}
let result = getName({name: 'xiaoming', age: 10});
console.log(result); // xiaoming
二、函数进阶
1. 设置默认参数值
ES2015 的语法可以为函数的参数设置默认值:
function fun(x = 10, y = 20) {
return x + y;
}
fun(); // 30
fun(1); // 21
fun(10, 20); // 30
- 未传递参数和未设置默认参数值时:
function fun(x, y) {
console.log(x); // undefind
console.log(y); // undefind
return x + y;
}
let result = fun();
console.log(result); // NaN
2. 立即执行函数
(function () {
let a = 10;
let b = 20;
console.log(a + b);
})();
// 30
- 功能:封装代码。
- 特点:
声明之后可以直接调用;
不可以多次调用;
某些第三方库实现封装。
作用域链:
- 每一个函数都会创建一个新的作用域;
- 函数外部无法访问函数内部的值;
- 函数内部的值可以访问函数外部的值(如果内部找不到值就去外部一层一层找)。
示例:树状图。
|-window
| |-str
| |-fun1
| | |-str
| | |-num
| | |-fun2
| | | |-str
| | | |-num
let str = "hello";
function fun1() {
let str = "world";
let num = 10;
function fun2() {
let str = 'fun2';
let num = 20;
console.log(str); // fun2
console.log(num); // 20
}
fun2();
console.log(str); // world
console.log(num); // 10
}
fun1();
console.log(str); // hello
3. 闭包
- 闭包函数:声明在一个函数中的函数,叫做闭包函数。
- 闭包:内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回之后。
- 闭包的特性: 内部函数未执行完,外部函数即使执行完成,外部函数中的变量也不会被销毁。
示例1:想要在 fun1 的外部打印 fun2 的结果。
function fun1() {
function fun2() {
console.log("I'm fun2");
}
}
利用 return在函数外部调用 fun2。
function fun1() {
function fun2() {
console.log("I'm fun2");
}
// 闭包的精华:return
return fun2;
}
const f = fun1();
f(); // I'm fun2
示例2:想要在 fun1 的外部求和。
function fun1() {
let n = 10;
let m = 20;
function fun2() {
return n + m;
}
return fun2;
}
const f = fun1(); // fun1的运行结果是fun2
let result = f();
console.log(result); // 30
代码封装:
ES5 的一个模块化的语法。
const module = (function () {
let a = 10;
let b = 20;
function add() {
return a + b;
}
return add;
})();
4. 箭头函数
作用: 简化写法。
const add = function (x) {
return x * x;
};
//简化
const add = (x) => {
return x * x;
};
//简化
// 参数 返回值
const fun = x => x * x;
示例:每秒输出一次名字。
const cat = {
name: "miaomiao",
sayName() {
let self = this;
setInterval(function () {
// window调用的setInterval
// this 指向 window,所以需要提前保存
console.log(self.name);
}, 1000)
},
// 使用箭头函数:
sayName() {
// 箭头函数:在哪里定义,this 就指向谁
setInterval(() => {
// this 指向 cat
console.log(this.name);
}, 1000);
},
};
cat.sayName(); // miaomiao
- 使用 function 定义的函数, this 取决于调用的函数;
- 使用箭头函数, this 取决于函数定义的位置;
箭头函数和普通函数的 this 指向不同:
- 普通函数指向的是 调用该函数的对象;
- 箭头函数是 在哪里定义,this 就指向谁。
三、面向对象
1.面向对象概述
面向对象是一种编程思想,这种编程思想可以当做一个学科来研究。
除了 JavaScript,例如 C++、Java、Python、PHP 等等编程语言都可以使用这种面向对象的编程思想来开发应用程序。
2.基本概念
类:类型、模板、统称。(狗类、鸟类)
对象:是类的一个实例,会具体到某一个事物上(天上飞的那只鸟,我家的那只猫)
继承:狗类继承至哺乳动物类,猫类也继承至哺乳动物类,继承后,子类可以使用父类的属性和方法。
3.新语法与旧语法
- ES5 面向对象语法:prototype;
- ES6(2015) :面向对象语法。
4.ES5 面向对象的知识
构造函数:用于创建对象的函数。
原型对象:prototype。
原型链:实现继承。
4.1 ES5构造函数
构造函数的函数名,首字母大写,如Person,Array,Function等…;
构造函数是用来创建对象用的。
// 构造函数
function Person(name, age) {
this.name = name;
this.age = age;
}
// 创建了一个对象,Person的实例
var person = new Person("hll", 18);
console.log(person.name);
4.2 原型对象
通过设置构造函数的 prototype 属性,可以扩展构造函数生成的对象。
通过原型对象,为构造函数生成的对象赋予新的方法。
Person.prototype.sayName = function () {
// this指向有构造函数生成的实例 person
console.log(`我的名字是${this.name}`);
};
Array.prototype.sayHello = function () {
// this指向有构造函数生成的实例 arr
console.log(你好,我的长度是${this.length}!);
}
let arr = [1, 2, 3, 4, 5, 1, 2, 3];
arr.sayHello();
// 你好,我的长度是 8
4.3 原型链(继承)
// 将子类的原型指向父类的实例
Student.prototype = new Person()
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function () {
console.log(`你好,我是${this.name}`);
};
function Student(name) {
this.name = name;
}
// 将子类的原型指向父类的实例
// 这样子类就可以继承并使用父类的方法
Student.prototype = new Person();
var student = new Student("Mary");
student.sayName();
// 你好,我是 Mary
5.ES6 面向对象的知识
5.1 Class关键字
ES6声明构造函数的语法是通过 class 和 constructor:
class Person {
// 变量写在 constructor 函数里面
constructor(name, age) {
this.name = name;
this.age = age;
}
// 方法
sayName() {
console.log(`我是${this.name}`);
}
}
let person = new Person("Lisa", 18);
person.sayName();
// 我是Lisa
5.2 继承
extends 关键字
super
语法:class Student extends Person {…}
class Person {
constructor(name) {
this.name = name;
}
sayName() {
console.log(`我是${this.name}`);
}
}
// ES6 继承 extends关键字
class Student extends Person {
constructor(name, age) {
//父级的属性 super关键字
super(name);
// 子级的就用this 关键字
this.age = age;
}
}
let student = new Student("Jacky", 22);
student.sayName(); //我是Jacky
console.log(student.age); //22