javascript中只有对象而没有类,当我们只有对象的时候如何引入继承?
在javascript中的每一个对象,除了一个特殊的,都有原型,它们都从原型继承所有的成员。
***原型是一个对象,***其他对象可以通过它实现属性继承。
let obj = Object.create(Object.prototype);
1.原型链(继承链)
当我们调用一个方法或属性,javascript引擎首先在这个对象里找目标,如果它找不到,它就会到对象的原型里找,如果还是找不到,它就会到原型的原型里找,一直往上找,直到找到或报错。
2.属性描述
let person = {name:'zijeak'};
console.log(person);
for(let key in person){
console.log(key);
}
console.log(Object.keys(person));
像上面这样,我们定义了一个只有name成员的对象,由于原型链继承,我们可以调用toString等继承来的方法,但当我们枚举这个对象是,却看不见这些继承来的方法:
为什么我们不能遍历元对象的成员呢?
原因在于:在javascript中,所有的属性都是有自己的特征的,有时,某些特征阻止一个属性被枚举。
let person = {name:'zijeak'};
let objectBase = Object.getPrototypeOf(person);
let descriptor = Object.getOwnPropertyDescriptor(objectBase,'toString');
console.log(descriptor);
我们可以为自己对象的属性添加这样的描述
let person = {name:'zijeak'};
// let objectBase = Object.getPrototypeOf(person);
// let descriptor = Object.getOwnPropertyDescriptor(objectBase,'toString');
// console.log(descriptor);
Object.defineProperty(person,'name',{
// 这里可以定义getter and setter
writable:false, //是否可以重写
enumerable:false, //是否可枚举
configurable:false, //是否可以删除该属性
});
person.name = 'Tom';
console.log(person);
console.log(Object.keys(person));
3.构造方法的原型
构造方法同样拥有原型属性,javascript函数就是对象,因此也有属性和方法。
这两个东西是一样的:
Object.getPrototypeOf(myObj);
myObj.__proto__
function Circle(radius){
this.radius = radius;
}
const circle = new Circle(1);
Circle.prototype // 这就是构造函数创建的对象的父母真身
这三个东西是一样的:
Object.getPrototypeOf(circle);
circle.__proto__;
Circle.prototype;
例如:
4.实例成员和原型对象成员
function Circle(radius){
this.radius = radius;
this.draw = function(){
console.log("draw");
}
}
const c1 = new Circle(1);
const c2 = new Circle(1);
从这个例子,我们可以看到,两个对象分别拥有一个draw方法的副本,这样的做法会在方法和对象越来越多时产生性能问题。
如何解决?
把方法放在原型中。
function Circle(radius){
this.radius = radius;
}
Circle.prototype.draw = function(){
console.log("draw");
}
const c1 = new Circle(1);
const c2 = new Circle(1);
因此,在javascript中,有两种成员:实例的属性和方法——实例成员(Instance members);原型对象成员(Prototype members)
我们可以重写原型成员:
Circle.prototype.toString = function(){
return "Circle with radius "+ this.radius;
}
5.枚举对象原型的成员
// 只返回实例成员
console.log(Object.keys(c1));
// 返回原型成员
for(let key in c1){
console.log(key);
}
console.log(c1.hasOwnProperty('radius'));
console.log(c1.hasOwnProperty('draw'));