在 JavaScript 中,函数也是属于对象,能够像其余对象同样访问属性,其中便有一个属性叫原型 prototype,值为一个对象,默认,原型有一个 constructor 属性,指向了构造函数自己。git
function Person () { return 'hi' } Person.prototype // {constructor: ƒ} Person.prototype.constructor // ƒ Person() {}
用图来表示:github
咱们能够对这个属性进行操做,但这个属性,只有在对函数进行构造调用的时候才会起做用编程
function Person (name) { this.name = name } Person.prototype.smart = true Person.prototype.run = function () { console.log('running') } // 或者一次性添加 Person.prototype = { smart: true, run() { console.log('running') } }
// ... let a = new Person('a') a.name // a a.smart // true a.run() // running
用来检测构造函数的原型是否存在于实例的原型链上函数
// ... let b = new Person('b') b instanceof Person // true b instanceof Object // true
该方法来判断是否自身属性,如:this
function Person () { this.name = 'Jon' } Person.prototype.name = 'people' Person.prototype.age = 18 let jon = new Person() jon.hasOwnProperty('name') // true jon.hasOwnProperty('age') // false
age 为原型上的属性,因此为 falsespa
该方法来判断对象是不是另外一个对象的原型,如:prototype
let base = { name: 'people', age: 18 } function Person () { this.name = 'Jon' } Person.prototype = base let jon = new Person() base.isPrototypeOf(jon) // true
当不知道对象的原型具体是哪一个的时候,可使用该方法来判断,如:3d
let base = { name: 'people', age: 18 } function Person () { this.name = 'Jon' } Person.prototype = base let jon = new Person() Object.getPrototypeOf(jon) // { name: 'people', age: 18 }
引用《MDN _ _proto_ _ 》 的解释:code
Object.prototype 的 _ _proto_ _ 属性是一个访问器属性(一个 getter 函数和一个 setter 函数), 暴露了经过它访问的对象的内部原型 (一个对象或 null)。
也就是说,每一个对象都有一个该属性,便携访问原型对象,直指原型对象:对象
let base = { name: 'people', age: 18 } function Person () { this.name = 'Jon' } Person.prototype = base let jon = new Person() jon.__proto__ // { name: 'people', age: 18 }
用图来表示:
与 prototype 不一样的是,_ _proto_ _ 是对象的属性,prototype 是构造函数的属性
该方法建立一个新对象,使用现有的对象来提供新建立的对象的 _ _proto_ _:
let base = { name: 'people', age: 18 } let jon = Object.create(base) jon.__proto__ // { name: 'people', age: 18 }
当访问对象的一个属性时,js 引擎会遍历自身对象的属性,若是找不到,便会去原型上查找该属性,若是仍是找不到,便会继续查找原型的属性,直到到 Object 原型
因为原型是一个对象,是对象便会有一个原型,有原型说明存在构造函数,如 Person 例子,查看原型的构造函数是啥:
// ... Person.prototype.__proto__.constructor // ƒ Object() { [native code] } Person.prototype.__proto__.constructor === Object // true
说明 Object 是 Person 原型 的构造函数
说明 Person 原型 的 _ _proto_ _ 会指向 Object.prototype,由于 _ _proto_ _ 能快捷访问原型:
// ... Object.getPrototypeOf(jon.__proto__) === Object.prototype // true // 或者 jon.__proto__.__proto__ === Object.prototype // true // 或者 Person.prototype.__proto__ === Object.prototype // true
用图表示就是:
举个例子:
// ... let a = new Person('a') a.toString() // "[object Object]"
Person 函数和原型上都没有 toString 方法,因此只能调用 Object 上的 toString 方法。
注意:基于同一个构造函数生成的对象,共享函数的原型,如:
// ... let b = new Person('b') b.name // b b.smart = false b.smart // false a.smart // false b.__proto__ === a.__proto__ // true
对 b 的 smart 属性进行修改,a 访问 smart 也有原先的 true 变为 false 了。
Object.prototype.__proto__ // null
null 是什么意思?此处无对象的意思,说明 Object.prototype 没有原型,查到这里就中止查找了,若是在找不到目标属性,就返回 undefined。
若是自身和原型上存在同名属性,会优先使用自身属性,例如:
function Person () { this.name = 'Jon' } Person.prototype.name = 'people' let jon = new Person() jon.name // Jon