原型
原型是对象数据类型所有,原型又分为显式原型和隐式原型:
// 语法糖形式
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
getName() {
return this.name;
}
getAge() {
return this.age;
}
}
const person = new Person('张三', 18);
person.getName(); // 张三
person.getAge(); // 18
// 构造函数形式
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.getName = getName; // 这种写法是为了内存空间优化,懂得人都懂
Person.prototype.getAge = getAge;
function getName() {
return this.name;
}
function getAge() {
return this.age;
}
const person = new Person('张三', 18);
person.getName(); // 张三
person.getAge(); // 18
我们看到上面两种方式都是创建了一个Person
对象(一个是类,一个是构造函数),对象初始状态下都含有一个prototype
属性,将Person.prototype
称之为显式原型,其属性值所指向的是一个空的Object
实列对象,默认添加两个属性(constructor
和__proto__
),constructor
指向对象本身,__proto__
指向Object.prototype
;Person
对象的实例person
,其含有一个__proto__
属性,将person.__proto__
称之为隐式原型,注意因为浏览器和移动端的兼容性,要想获取一个对象的隐式原型,是不能通过.__proto__获取,正确的方式是通过Object.getPrototypeof()
或者Reflect.getPrototypeof
获取,person.__proto__
指向Person.prototype
;
原型链
通常我们所说原型链其实就是指隐式原型形成,在查找一个对象属性时,比如上述的person
对象,我们先从自身查找,即person.hasOwnProperty()
返回为true
的属性,如果对象自身没有查到我们要查找的属性,我们就会去该对象的隐式原型(__proto__
)上去查找,直到查找到Object.prototype
上,因为在Object.prototype.__proto__
为null
;上面我们一层一层的去查找属性拥有的属性值,这样的关系我们映射为是原型链这个概念。
原型继承
一个对象a
可以访问另一个对象b
属性,并且是通过__proto__
去访问的,那么这种方式a
继承b
,我们称之为原型继承;我们可以通过一些官方所给的api
去快速实现原型继承:
// 方式一:
const b = {name: '张曼玉', age: 18};
const a = Object.create(b);
console.log(a.name); // 张曼玉
console.log(a.age); // 18
// 方式二:
const b = {name: '张曼玉', age: 18};
Object.setPrototypeof(a, b);// or Reflect.setPrototypeof(a, b);
原型继承在一定程度上可以防止一个对象的属性被污染,比如a
对象添加属性不会污染到b
对象的属性;