JavaScript study notes (XII) prototype

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 constructorproperty 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 prototypeattribute, the function prototype object points

    The prototype object 's constructorattributes, 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 the

    Some 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 constructorattributes are directed Function, __proto__the properties are directedFunction.prototype

    Because the constructor is through new Functionto 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 constructor prototypeproperty __proto__attributes are directedObject.prototype

    And Objectthe prototypeproperties 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 constructorproperty, where there is prototypeproperty, 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学习笔记

Guess you like

Origin www.cnblogs.com/wsmrzx/p/12199295.html