本书未发布
原型
原型
prototype 和 proto
- 每个函数都有一个 prototype 属性(即显式原型),他默认指向一个空的 Object 对象,即原型对象,但是,
Object
函数除外 - 在函数创建的时候会添加显式原型属性
- 在实例化对象的时候,会添加隐式原型
const fn = new Fn()
Fn.prototype instanceof Object // true
Object.prototype instanceof Object // false
Function.prototype instanceof Object // true
而原型对象有一个
constructor
属性,他又指向了函数本身实例对象的隐式原型的值等于构造函数的显式原型 (或者可以说是,构造函数的
prototype
指向了原型,原型的constructor
指向了构造函数)但是,
Function
除外,function Function()
的显式原型和隐式原型都指向了Function
原型所有函数(包含
Function
)都是Function
的实例Function.__proto__ === Function.prototype // true
Object
的原型对象是原型链的尽头每个实例对象都有一个 proto 属性(即隐式原型), 这是一个非标准的属性, 建议在开发和调试中使用, 在线上不要使用
如下所示,当 fn 对象在调用 test 方法的时候,会先在自身上找,如果找不到,则会顺着隐式原型去原型上找
function Fun() {
console.log(123)
}
// Fun 也是 Function 的实例对象,上面的定义,可以看成是 const Fun = new Function()
Fun.prototype.constructor === Fun // true
Fun.prototype.test = function() {
console.log('test')
}
const fn = new Fun()
fn.__proto__ === Fun.prototype // true
fn.test()
应用
function Person(name, age) {
this.name = name
this.age = age
this.setName = function(name) {
this.name = name
}
}
// 如果像上面这样写的话,在多次 new Person 的时候,每个对象都有一个相同的 setName 的函数,
// 这样就会浪费内存空间,所以可以尝试把该方法定义到原型上,如下
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.setName = function(name) {
this.name = name
}
原型链
- 访问一个对象的属性的流程
- 会先在自身上找
- 如果自身上找不到,再沿着 proto 原型链往上查找
- 如果最终没有找到,则返回
undefined
- 在原型链的查找过程中,一直都是按照隐式原型来查找的,所以原型链也可以成为是隐式原型链
- 在给对象设置属性的时候,并不会查找原型链,如果当前对象中没有这个属性,那么就直接给这个对象添加上这个属性
函数
- 所有函数的隐式原型都是一样的
function Fn() {
this.test1 = function() {
console.log('test1')
}
}
Fn.prototype.test2 = function() {
console.log('test2')
}
const fn = new Fn()
fn.test1()
fn.test2()
fn.toString()
fn.test3 // undefined
fn.test3() // 报错,fn.test3 is not a function
对象
const a = new Object()
继承
原型链继承
- 构造函数的实例对象自动拥有构造函数原型对象的属性(和方法)
- 要实现原型链的继承,得让子类型的原型为父类型的一个实例对象
function Supper() {
this.supperProp = 'supper'
}
Supper.prototype.showSupperProp = function() {
console.log(this.supperProp)
}
// 子类型
function Sub() {
this.subProp = 'sub'
}
// 子类型的原型为父类型的实例对象
Sub.prototype = new Supper()
// 让子类型原型的 constructor 指向子类型
Sub.prototype.constructor = Sub
Sub.prototype.showSubProp = function() {
console.log(this.subProp)
}
var sub = new Sub()
sub.showSupperProp() // 'supper'
sub.showSubProp() // 'sub'
instanceof 和 isPrototype
A instanceof B
是用来判断 A 是否是 B 的实例
function Foo(){}
var f1 = new Foo()
f1 instanceof Foo // true
f1 instanceof Object // true
Object instanceof Function // true
Object instanceof Object // true
Function instanceof Function // true
Function instanceof Object // true
function Foo() {}
Object instanceof Foo // false
isPrototype()
是用来判断一个对象是否是某个实例的原型对象
hasOwnProperty 和 in
hasOwnProperty
是只会在自身对象中查找是否存在该属性in
先会在自身上查找, 如果找不到, 则去原型上查找
constructor
constructor
是表示当前的实例到底是由哪个构造函数产生的
面试题
1.
function F() {}
Object.prototype.a = function() {
console.log('a')
}
Function.prototype.b = function() {
console.log('b')
}
const f = new F()
f.a() // 'a'
f.b() // 报错
F.a() // 'a'
F.b() // 'b'