第四天的课
作用域
- 全局、函数、块
全局
- 全局对象:如果在浏览器中允许 js,那么全局对象就是 window。
- 直接声明的变量都是由全局对象调用的。
var site = "zhang";
console.log(site); // zhang
console.log(window, site); // zhang
console.log(site === window.site); // true
// 补充:使用let声明时,window.site 的值为underfined
let b = "zzz";
console.log(window.b); //underfined
函数作用域
- 作用域:先访问函数内部,若没有要返回的变量,则再从函数的上一级作用域中寻找。链
- 私有变量(成员):在函数外无法调用函数内部声明的变量
let c = "zhang";
function item() {
let d = "zzz";
return "c = " + c;
}
//访问函数内部变量
console.log(d); // 报错
// 从函数内向外获取 c
console.log(item()); // c=zhang
块作用域
- 大括号内会创造出一个块作用域,例如 if(),while()
在块作用域中,得是有 let 和 count 声明变量,不能使用 var,var 会泄露到外部。
let a = 1;
{
count B = 22;
var c = "张";
};
console.log(a); //1
console.log(B); // 报错
console.log(c); // 张
闭包
含义
- 在讲述之前先看一下代码
let c = 100;
function sum(a, b) {
return a + b + c;
}
console.log(sum(2, 3)); // 105
- 当前函数可以访问到上一级/外部的自由变量,其为闭包
- 即可以访问自由变量的函数,为闭包,
- 理论上将,所有函数都可以是闭包。
应用
- 通过闭包来访问函数内部的私有变量
function demo1() {
// 私有变量
let email = "a@qq.com";
return function () {
return email;
};
}
console.log(demo1()()); // a@qq.com
循环
while
-
- 入口判断 – 在开头进行条件建立
-
如果循环条件不符,则不会运行循环。
const colors = ["red", "green", "blue"];
// 循环变量的初始化
let i = 0;
// i < colors.length 为循环条件
while (i < colors.length) {
console.log(colors[i]);
// 更新循环条件,否之会进入死循环
i = i + 1;
//简化: i += 1;和 i++(自增1)
}
// red
// green
// blue
-
- 出口判断 – 在结尾进行条件建立 do–while
-
哪怕循环条件不符,while 仍会运行一次
const colors = ["red", "green", "blue"];
// 循环条件不满足
let i = 10;
// i < colors.length 为循环条件
do {
// console.log(colors[i]);
console.log("我执行了一次");
i = i + 1;
//简化: i += 1;和 i++(自增1)
} while (i < colors.length);
// 我执行了一次
for 循环
while 循环的简化
const colors = ["red", "green", "blue"];
for (i = 0; i < colors.length; i++) {
console.log("%c%s", "color:green", colors[i]);
//%c是css样式, %s是后面的参数
}
// red
// green
// blue
对象的遍历 for-in
const lesson = {
name: "js",
number: 88,
};
for (let key in lesson) {
console.log(lesson[key]);
// console.log(lesson[key]);
//不适用 lesson.key,会因为标识符出错
}
// js
// 88
迭代器
- 将所有类型的数组的遍历进行了统一操作
- 无法遍历对象
1. for-of
const colors = ["red", "green", "blue"];
for (let item of colors) {
console.log(item);
}
// red
// green
// blue
构造函数
补充常识:
- 任何一个函数都是对象,有一个属性叫 prototyp(原型属性)
- 函数有两个功能:
- 基本功能是封闭操作步骤
- 扩展功能:当成对象的构造器,构造函数,对象生成器来使用
- 在 js 中没有“类”的概念,都是通过原型来实现继承的
含义
- 为了区别函数这两个功能,当一个函数当成构造函数来使用是,必须使用“new”
- 通过构造函数的创建对象的过程中,叫做“类的实例化”
- 此时,构造函数可以看成一个类
function User() {}
//当成普通函数调用
const user = User();
console.log(user, typeof user); //undefined undefined
//当成构造函数调用new
const user = new User();
// user为对象
console.log(user, typeof user); //User {} 'object'
构造函数的内部
- 内部会自动创建一个 this,指向新生成的对象
- 第二步是给这个新生成的对象添加一些成员(属性,方法)
- 返回这个新对象(自动返回)
function User(name, email) {
this.name = name;
this.email = email;
}
const user = new User("admin", "admin@php.cn");
console.log(user.email, user.name); // admin@php.cn admin
// user对象的原型
console.log(user.__proto__); //{constructor: ƒ}
// user的构造函数的原型
console.log(USer.prototype); //{constructor: ƒ}
console.log(user.__proto__ === User.prototype); //true
补充
user 对象的原型属性永远指向它的构造函数的原型属性对象
类与继承
类
- 类为模板,类似于工厂里的模具
-
构造方法:初始化对象
-
原型方法(共享方法):将方法放到原型属性里
因为 构造函数对象的原型对象上的成员,而已被所有实例化所共享 -
静态方法:不需要实例化(new,class),直接用类来调用
-
私有成员:在类内声明内部的变量,
通过访问器属性,伪装成属性的方法,例如 get,set 来从外部来调用类内部的私有成员
class User1 {
// 构造方法
constructor(name, email) {
this.name = name;
this.email = email;
}
//原型方法
show(){
retrun { name: this.name, email:this.email, age:this.age1};
}
//静态方法
static fetch(){
return `static function`+ this.userName;
// 静态成员中的this表示的就是当前的类
}
// 静态属性/变量
static userName = "猪八戒";
// 4. 私有成员,在函数内声明内部的变量
#age1= 50;
// 5. 声明访问器属性,伪装成属性的方法,例如 get,set
get age1() {
return this.#age1;
}
}
const user = new User1("孙悟空","qq.com");
// 构造方法调用
console.log(user);
// User1 {name: '孙悟空', email: 'qq.com'}
// 原型方法调用
console.log(user.show());
// {name: '孙悟空', email: 'qq.com'}
//静态方法调用
console.log(User1.fetch());
//static function
//私有成员的外部调用
console.loh(user.age1); //50
继承
-
通常是对父类进行一些扩展(添加一些新的属性和方法)
-
第一步必须将父类的构造方法来执行一下,否则 this 用不了
-
第二部给类的新成员初始化
// 声明一个类
class User1 {
constructor(name, email) {
this.name = name;
this.email = email;
}
show(){
retrun { name: this.name, email:this.email, age:this.age1};
}
}
// 进行继承
class Child extends User1 {
//构造初始化
constructor(name,email,gender){
// 引入父类的参数
super(name,email);
this.gender = gender;
}
// 父类的原型方法
show(){
return { name: this.name, email:this.email, age:this.age1 ,gender:this.gender};
}
const child = new Child("欧阳老师","oy@qq.com","男");
console.log(child.show());
//name: '欧阳老师', email: 'oy@qq.com', age: 50, gender: '男