原型链与继承
JavaScript 原型链、继承、类、实例、构造函数、typeof
和 instanceof
的区别
在 JavaScript 中,原型链和继承是核心概念之一。通过原型链,对象可以访问其构造函数的原型对象上的属性和方法。以下是对这些概念的详细解释,并结合 Vue3 提供示例。
1. 原型链与继承
每个对象都有一个内部属性 [[Prototype]]
,它指向该对象的原型对象。当通过对象访问一个属性或方法时,如果对象本身没有该属性或方法,则会沿着原型链向上查找,直到找到或者到达原型链的尽头(即 null
)。
例如:
function Person(name) {this.name = name;
}
Person.prototype.sayHello = function() {console.log(`Hello, my name is ${this.name}`);
};const person = new Person("Alice");
person.sayHello(); // 输出: Hello, my name is Alice
在这里,sayHello
方法并没有直接定义在 person
实例上,而是通过原型链从 Person.prototype
上继承而来。
2. 类与实例
ES6 引入了 class
关键字,使类的定义更加直观。实际上,class
是基于原型继承的语法糖。例如:
class Car {constructor(brand) {this.brand = brand;}getBrand() {return this.brand;}
}const car = new Car("Toyota");
console.log(car.getBrand()); // 输出: Toyota
这里,Car
是一个类,car
是它的实例。getBrand
方法定义在 Car.prototype
上。
3. 构造函数
构造函数是一个用于创建对象的函数。使用 new
关键字调用构造函数时,会执行以下步骤:
- 创建一个新对象。
- 将该对象的
[[Prototype]]
指向构造函数的prototype
属性。 - 执行构造函数代码,将属性赋值给新对象。
- 返回新对象。
4. typeof
与 instanceof
的区别
typeof
返回一个字符串,表示变量的基本类型(如"number"
,"string"
,"object"
,"function"
等)。instanceof
判断一个对象是否是由某个构造函数创建的实例。例如:
let str = "hello";
console.log(typeof str); // 输出: stringlet car = new String("hello");
console.log(typeof car); // 输出: object
console.log(car instanceof String); // 输出: true
注意:typeof
对于对象类型返回 "object"
,而 instanceof
可以更精确地判断对象的构造函数。
5. Vue3 示例讲解
Vue3 使用了原型链来扩展实例的功能。例如,Vue.prototype
上挂载了一些常用方法,如 $set
、$delete
和 $watch
。以下是一个简单的 Vue3 示例:
// 定义一个 Vue 类似的构造函数
function Vue(options) {this.data = options.data;this.methods = options.methods;
}// 在原型上挂载方法
Vue.prototype.$set = function(key, value) {this.data[key] = value;
};
Vue.prototype.$delete = function(key) {delete this.data[key];
};// 创建实例
const app = new Vue({data: { message: "Hello Vue3!" },methods: { greet: function() { console.log(this.data.message); } }
});app.$set("name", "Vue3");
console.log(app.data.name); // 输出: Vue3
app.$delete("message");
console.log(app.data.message); // 输出: undefined
在这个例子中,$set
和 $delete
方法通过原型链被所有 Vue 实例共享。