Look prototype and prototype chain before, always see stumbled recently to take advantage of free re-order a bit, in fact, not difficult to find
Here we follow step by step, completely clear prototype and prototype chain bar
1, prototype
- Each instance of an object has a
constructor
property to it constructor
function Person(name) {
this.name = name
}
var person = new Person('Steve') // 自定义构造函数
var string = new String('Hello') // 原生的构造函数
console.log(person.constructor === Person)
console.log(string.constructor === String)
/*
* 执行结果:
* true
* true
**/
Each function object (including constructor) has an
prototype
attribute, the function prototype object pointsThe prototype object 's
constructor
attributes, pointing to the function itself
function Person(name) {
this.name = name
}
var person = new Person('Steve') // 自定义构造函数
var string = new String('Hello') // 原生的构造函数
console.log(Person.prototype.constructor === Person)
console.log(String.prototype.constructor === String)
/*
* 执行结果:
* true
* true
**/
Each target has a
[[prototype]]
private property, pointing to its prototype object constructor, but this property is not allowed to access theSome browsers (such as Chrome) provides
__proto__
property is used to access[[prototype]]
a private property
function Person(name) {
this.name = name
}
var person = new Person('Steve') // 自定义构造函数
var string = new String('Hello') // 原生的构造函数
console.log(person.__proto__ === Person.prototype)
console.log(string.__proto__ === String.prototype)
console.log(Person.__proto__ === Function.prototype)
console.log(String.__proto__ === Function.prototype)
/*
* 执行结果:
* true
* true
* true
* true
**/
Constructor
constructor
attributes are directedFunction
,__proto__
the properties are directedFunction.prototype
Because the constructor is through
new Function
to create, they are examples of Function objects, including Object and Function
function Person(name) {
this.name = name
}
console.log(Person.constructor === Function)
console.log(Person.__proto__ === Function.prototype)
console.log(String.constructor === Function)
console.log(String.__proto__ === Function.prototype)
console.log(Function.constructor === Function)
console.log(Function.__proto__ === Function.prototype)
console.log(Object.constructor === Function)
console.log(Object.__proto__ === Function.prototype)
/*
* 执行结果:
* true
* true
* true
* true
* true
* true
* true
* true
**/
In addition
Object
, other constructorprototype
property__proto__
attributes are directedObject.prototype
And
Object
theprototype
properties of__proto__
attribute pointsnull
function Person(name) {
this.name = name
}
console.log(Person.prototype.__proto__ === Object.prototype)
console.log(String.prototype.__proto__ === Object.prototype)
console.log(Function.prototype.__proto__ === Object.prototype)
console.log(Object.prototype.__proto__ === null)
/*
* 执行结果:
* true
* true
* true
* true
**/
Finally, to sum up the picture, although it looks a bit complicated, but as long as we find the law, will be very simple
Category suggest that you look at, pay attention to where there is constructor
property, where there is prototype
property, where there is __proto__
property
2, the prototype chain
(1)原型链
上面我们说过,所有对象都有 __proto__
属性,并且这个 __proto__
属性指向一个原型对象
因为原型对象也是对象,这个原型对象也有 __proto__
属性,我们把这种关系称为原型链
(2)属性访问
当需要访问一个对象的属性时,首先从该对象开始查找,如果能够找到,那么到此返回
如果没有找到,就在该对象的 __proto__
属性指向的原型对象中继续查找,如果能够找到,那么到此返回
如果没有找到,那么一直往上查找原型对象,直至 __proto__
属性指向 null
,也就是原型链的顶端
若原型链上的所有原型对象都没有该属性,则返回 undefined
function Person(name) { this.name = name }
Person.prototype.getName = function() { return this.name }
var person = new Person('Steve')
var name = person.getName() // 在 Person.prototype 中找到
var description = person.toString() // 在 Object.prototype 中找到
var age = person.age // 在原型链中无法找到
console.log(name)
console.log(description)
console.log(age)
/*
* 执行结果:
* Steven
* [object Object]
* undefined
**/
(3)属性检测
in
操作符:检测属性是否在对象的原型链上hasOwnProperty
方法:检测属性是否来自对象本身
function Person(name) { this.name = name }
Person.prototype.getName = function() { return this.name }
var person = new Person('Steve')
console.log('age' in person)
console.log('name' in person)
console.log('getName' in person)
console.log('toString' in person)
console.log(person.hasOwnProperty('age'))
console.log(person.hasOwnProperty('name'))
console.log(person.hasOwnProperty('getName'))
console.log(person.hasOwnProperty('toString'))
/*
* 执行结果:
* false
* true
* true
* true
* false
* true
* false
* false
**/
3、为什么要使用原型
JavaScript 中的继承是基于原型的,原型的作用在于不同实例对象之间可以共享数据,节省内存
function Person(name) { this.name = name }
Person.prototype.getName = function() { return this.name }
var person1 = new Person('Steve')
var person2 = new Person('Steven')
// 不同实例对象 person1 和 person2 都可以使用在 Person.prototype 上定义的 getName(共享数据)
// 从而避免在每个实例对象上都要重复定义 getName(节约内存)
var name1 = person1.getName()
var name2 = person2.getName()
console.log(name1)
console.log(name2)
/*
* 执行结果:
* Steve
* Steven
**/
4、要怎么样使用原型
为一个对象添加原型有三种方式,分别是 new
关键字、class
关键字和 Object.create
方法
其中,class
关键字其实是 new
关键字的语法糖
new
关键字
function Person(name) {
this.name = name
}
Person.prototype.getName = function() {
return this.name
}
var person = new Person('Steve')
var prototype = Object.getPrototypeOf(person)
console.log(prototype)
class
关键字
class Person {
constructor(name) {
this.name = name
}
getName() {
return this.name
}
}
var person = new Person('Steve')
var prototype = Object.getPrototypeOf(person)
console.log(prototype)
Object.create
方法
var object = {
name: 'Steve',
getName: function() {
return this.name
}
}
var person = Object.create(object)
var prototype = Object.getPrototypeOf(person)
console.log(prototype)
【 阅读更多 JavaScript 系列文章,请看 JavaScript学习笔记 】