1. 作用域
- 全局
- 函数
- 块
1.1 全局作用域
<script>
let a = 1;
console.log(a);
//1
</script>
1.2 函数作用域
let a = 1;
//console.log(a);
function foo() {
let a = 5;
return a;
}
console.log(foo());
//5
1.3 块作用域
- 只有在块作用域中使用let或const声明才有效,使用var无效(作用域会提升)
{
let m = 8;
const M = 9;
}
console.log(M);
console.log(m);
//均会报错
2. 闭包
- 用来访问函数内部的局部变量
function foo() {
let a = 0;
return function f(params) {
return a;
}
}
let f = foo();
console.log(f());
3. 循环
- 用于遍历数组,对象
3.1 while loop
- 数组
const arr = ["cat", "dog", "pig"];
let i = 0;
while (i < arr.length) {
console.log(`animal: ${arr[i]}`);
i += 1;
}
//animal: cat
//animal: dog
//animal: pig
3.2 do…while loop
- 数组
let i = 1;
do {
i += 1;
console.log(`animal: ${arr[i]}`);
} while (i < arr.length - 1);
//animal: pig
3.3 for…in
- 对象
const stu = {
id: 1,
name: "Jack",
gender: "male",
graduate: false
}
for (const key in stu) {
console.log("%c%s", "color:green", stu[key]);
}
//1
//Jack
//male
//false
3.3 迭代器
for (const item of arr) {
console.log(item);
}
//animal: cat
//animal: dog
//animal: pig
4. 构造函数和原型
JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。
准确地说,这些属性和方法定义在Object的构造器函数(constructor functions)之上的prototype属性上,而非对象实例本身。
- 函数本身是对象,其中一个属性为prototype
- 可作为对象的构造器,构造函数
- javascript没有“类”的概念,都是通过原型来实现继承
4.1 构造函数
- 在函数中不再创建对象并返回
- 命名一般以大写字母开头,以区分构建函数和普通函数
- 函数作为构造函数使用时,必须使用new关键字
- 类的实例化:通过构造函数创建对象的过程(此时构造函数可看成类)
function User(name, age) {
this.name = name;
this.age = age;
this.info = function () {
return { name: this.name, age: this.age };
}
}
4.2 原型
- 每一个函数的特殊属性:prototype
- 原型函数的实例的proto属性,相当于原型函数的prototype属性
- 每个实例对象都从原型中继承了一个constructor属性,该属性指向了用于构造此实例对象的构造函数。
function User(params) {
this.p = params;
}
const user = new User("hehe");
console.log(user);
//user对象的原型
console.log(user.__proto__);
//user构造函数的原型
console.log(User.prototype);
console.log(user.__proto__ === User.prototype);
原型链
- 当访问原型函数实例的属性时,会先检查该实例是否具有要访问的属性。
- 如果 实例 没有这个属性, 然后浏览器就会在 实例 的 proto 中查找这个属性(也就是 原型函数的.prototype)
- 如果 实例 的 proto 有这个属性, 那么它的 proto 上的这个属性就会被使用.
- 否则, 如果 实例 的 __proto 没有这个属性, 浏览器就会去查找它的 proto 的 proto ,看它是否有这个属性.
- 默认情况下, 所有函数的原型属性的 proto 就是 window.Object.prototype.
- 所以 实例 的 proto 的 proto (也就是 原型函数的.prototype 的 proto (也就是 Object.prototype)) 会被查找是否有这个属性.
- 如果没有在它里面找到这个属性, 然后就会在 实例 的 proto 的 proto 的 proto 里面查找.
- 然而这有一个问题: 实例 的 proto 的 proto 的 proto 不存在.
- 最后, 原型链上面的所有的 proto 都被找完了, 浏览器所有已经声明了的 proto 上都不存在这个属性
- 然后就得出结论,这个属性是 undefined.
常见定义做法:
- 在构造函数内定义属性
- 在其prototype属性上定义方法
function User(name, age) {
this.name = name;
this.age = age;
// this.info = function () {
// return { name: this.name, age: this.age };
// }
}
//将info()放到原型prototype属性中
User.prototype.info = function () {
return { name: this.name, age: this.age };
};
//生成对象
const user = new User("Tom", 23);
console.log(user);
//User {name: "Tom", age: 23}
console.log(user.info());
//{name: "Tom", age: 23}
5. 类与继承
- 子类继承父类的属性
- 可以重写父类方法
- 可以有新的属性
- 不能继承父类的私有属性
class Animal {
//构造方法
constructor(name, leg) {
this.name = name;
this.leg = leg;
}
//原型方法
info() {
return { name: this.name, leg: this.leg, isPet: this.#isPet };
}
//静态方法
static eat() {
return "food";
}
//静态属性
static nature = "creature";
//私有属性
#isPet = false;
//访问器方法 getter, setter
get isPet() {
return this.#isPet;
}
set isPet(value) {
this.#isPet = value;
}
}
const cat = new Animal("Cat", 4);
const bird = new Animal("Bird", 2);
console.log(cat.info());
//{name: "Cat", leg: 4, isPet: false}
console.log(bird.info());
//{name: "Bird", leg: 2, isPet: false}
console.log(`动物吃:${Animal.eat()}`);
//动物吃:food
console.log(`动物本身是:${Animal.nature}`);
//动物本身是:creature
console.log(`猫是宠物吗? ${cat.isPet}`);
//猫是宠物吗? false
cat.isPet = true;
console.log(`猫是宠物吗? ${cat.isPet}`);
//猫是宠物吗? true
//继承
class Dog extends Animal {
//继承
//第一步必须执行父类构造方法,否则无法使用this
constructor(name, type) {
super(name, 4);
//新成员初始化
this.type = type;
}
info() {
return { name: this.name, leg: this.leg, type: this.type };
}
//父类的私有属性不会被继承
}
const dog = new Dog("Dog", "哈士奇");
console.log(dog.info());
//{name: "Dog", leg: 4, type: "哈士奇"}