一、作用域与闭包
1.作用域
1.全局作用域
(1) 全局作用域在页面打开时被创建,页面关闭时被销毁
(2) 写在 script 标签中的变量和函数,作用域为全局,在页面的任意位置都可以访问到
(3) 在全局作用域中有全局对象 window,代表一个浏览器窗口,由浏览器创建,可以直接调用
(4) 全局作用域中声明的变量和函数会作为 window 对象的属性和方法保存
ver name = 'php中文网';
console.log(name);
console.log(window.name);
2.函数作用域
(1) 调用函数时,函数作用域被创建,函数执行完毕,函数作用域被销毁
(2) 每调用一次函数就会创建一个新的函数作用域,他们之间是相互独立的
(3) 在函数作用域中可以访问到全局作用域的变量,在函数外无法访问到函数作用域内的变量
(4) 在函数作用域中访问变量、函数时,会先在自身作用域中寻找,若没有找到,则会到函数的上一级作用域中寻找,一直到全局作用域
(5) 在函数作用域中也有声明提前的特性,对于变量和函数都起作用,此时函数作用域相当于一个小的全局作用域
(6) 在函数作用域中,不使用变量关键字声明的变量,在赋值时会往上一级作用域寻找已经声明的同名变量,直到全局作用域时还没找到,则会成为 window 的属性
(7) 在函数中定义形参,等同于声明变量
let site = 'php中文网';
function getSite() {
// 在函数内部可以访问到外部的全局变量
// 私有成员,仅限在当前作用内访问, 外部不可见
let domain = 'php.cn';
return `${site} [ ${domain} ]`;
}
console.log(getSite());
3.块作用域
(1)用{}创建快作用域
(2) let, const 支持块作用域; var 不支持块作用域
{
let a = 1;
const B = 'hello';
}
console.log(a, B);
2.闭包:能够访问自由变量的函数;理论上讲,所有函数都是闭包
let c = 100;
function sum(a, b) {
// 自由变量,函数参数以外的变量;c 为自由变量
return a + b + c;
}
console.log(sum(4, 5));
// 通过闭包来访问内部的私有变量;
function demo1() {
// 私有变量
let email = 'a@qq.com';
return function d() {
// 对于这个子函数来说,email就是它的自由变量
return email;
};
}
console.log(demo1()());
二、类与类的继承
1.类: 使用 class 关键字实现类
class User1 {
// 构造方法:初始化对象的
constructor(name, email) {
this.name = name;
this.email = email;
}
// 原型方法(共享方法),通过对象来调用的
show() {
return { name: this.name, email: this.email, age: this.#age };
}
// 静态方法: 不需要实例化(new class),直接用类来调用
static fetch() {
// 静态成员中的this表示的就是当前的类
return this.userName;
}
// 静态属性/变量
static userName = '灭绝小师妹';
// 私有成员
#age = 50;
// 还可以声明访问器属性: 伪装成属性的方法,有get,set
// 使用访问器属性来访问私有成员
get age() {
return this.#age;
}
set age(value) {
if (value >= 18 && value < 60) this.#age = value;
else console.log('年龄非法');
}
}
const user1 = new User1('天蓬老师', 'tp@qq.com');
console.log(user1.show());
// 静态方法直接用类调用
console.log(User1.fetch());
console.log('my age = ', user1.age);
user1.age = 160;
console.log('my age = ', user1.age);
user1.age = 32;
console.log('my age = ', user1.age);
2.继承:使用 extends 关键字实现继承
// 继承,通常是对父类进行一些扩展(添加一些新的属性或方法)
class Child extends User1 {
constructor(name, email, gender) {
// 第一步必须将父类的构造方法来执行一下,否则this用不了
super(name, email);
// 第二步给子类的新成中去初始化
this.gender = gender;
}
// 父类的原型方法
show() {
return { name: this.name, email: this.email, gender: this.gender };
}
}
const child = new Child('欧阳老师', 'oy@qq.com', '男');
console.log(child.show());