学习文章:这可能是掘金讲「原型链」,讲的最好最通俗易懂的了,附练习题!
prototype和__proto__有什么关系
构造函数
在 JavaScript 中,用 new 关键字来调用的函数,称为构造函数,主要功能为初始化对象,按照规范,构造函数首字母一般大写。
function Person(name, age) { // Person就是构造函数
this.name = name
this.age = age
}
构造函数的实例
当构造函数以 new 关键字调用时,会创建一个新的内存空间,标记为构造函数的实例
const person1 = new Person('小明', 20) // person1是Person构造函数的实例
const person2 = new Person('小红', 30) // person2也是Person构造函数的实例
关系1:构造函数
的prototype和其 实例 的__proto__指向同一个地方
函数定义方式
- 声明式函数定义
function fn1(name, age) {
console.log(`我是${name}, 我今年${age}岁`)
}
fn1('Anthony', 20) // 我是Anthony, 我今年20岁
- 函数表达式
const fn2 = function(name, age){
console.log(`我是${name}, 我今年${age}岁`)
}
fn2('Anthony', 20) // 我是Anthony, 我今年20岁
- 箭头函数
const arrowFn = (name, age) => {
console.log(`我是${name}, 我今年${age}岁`)
}
arrowFn('Anthony', 20) // 我是Anthony, 我今年20岁
只考虑函数声明,以上三种方式都可以用new Function 的形式来声明,等同于:
const fn1 = new Function('name', 'age', 'console.log(`我是${name}, 我今年${age}岁`)')
fn1('Anthony', 20) // 我是Anthony, 我今年20岁
const fn2 = new Function('name', 'age', 'console.log(`我是${name}, 我今年${age}岁`)')
fn2('Anthony', 20) // 我是Anthony, 我今年20岁
const arrowFn = new Function('name', 'age', 'console.log(`我是${name}, 我今年${age}岁`)')
arrowFn('Anthony', 20) // 我是Anthony, 我今年20岁
上面说过,在 JavaScript 中,用 new 关键字来调用的函数,称为构造函数,所以Function也是构造函数, fn1 ,fn2 ,arrowFn函数都是它的实例。
关系2:Function构造函数
的prototype和其 实例函数
的__proto__指向同一个地方
创建对象方式
- 利用对象字面量创建对象
- 利用new Object() 创建对象
- 利用构造函数创建对象,创建出来的对象都是Function构造函数的实例,和上文一样
- Object.create创建对象,创建出来的是一个空原型的对象,不讨论它
// 字面量创建对象
const person2 = {name: 'Anthony', age: 20}
console.log(person2) // { name: 'Anthony', age: 20 }
// new Object创建对象
const person3 = new Object()
person3.name = 'Anthony'
person3.age = 20
console.log(person3) // { name: 'Anthony', age: 20 }
// Object.create创建对象
const person4 = Object.create({})
person4.name = 'Anthony'
person4.age = 20
console.log(person4) // { name: 'Anthony', age: 20 }
字面量创建对象的本质就是new Object创建对象
// new Object创建对象
const person2 = new Object()
person2.name = 'Anthony'
person2.age = 20
console.log(person2) // { name: 'Anthony', age: 20 }
上面说过,在 JavaScript 中,用 new 关键字来调用的函数,称为构造函数,所以Object也是构造函数, person2,person3都是Object构造函数的实例
关系3:Object构造函数
的prototype和其 实例对象
的__proto__指向同一个地方
Object构造函数本质上也是函数,因此它是Function构造函数的实例
关系4:Function构造函数
的prototype和其 实例Object构造函数
的__proto__指向同一个地方
Function构造函数本质上也是函数,因此它是Function构造函数的实例
关系5:Function构造函数
的prototype和其 实例Function构造函数
的__proto__指向同一个地方
如果a是b的prototype,b即是a的constructor
原型链
什么是原型链
__proto__的路径
就叫原型链
原型链终点
三条原型链结尾都是Object.prototype
,而Object.prototype的__proto__
指向null
,因此null
是原型链的终点
原型继承
原型继承
就是实例
可以使用构造函数上的prototype
中的方法,实例先找自身有没有此方法,没有就沿着原型链找
function Person(name) { // 构造函数
this.name = name
}
Person.prototype.sayName = function() { // 往原型对象添加方法
console.log(this.name)
}
const person = new Person('Anthony') // 实例
// 使用构造函数的prototype中的方法
person.sayName() // Anthony
instanceof
作用
判断B的prototype是否在A的原型链上
使用方法
A instanceof B
总结
构造函数
的prototype和其 实例 的__proto__指向同一个地方函数
是Function构造函数
的实例,即Function构造函数
的prototype和其 实例函数
的__proto__指向同一个地方对象
是Object构造函数
的实例,即Object构造函数
的prototype和其 实例对象
的__proto__指向同一个地方Function构造函数
是Function构造函数
的实例,即Function构造函数
的prototype和其 实例Function构造函数
的__proto__指向同一个地方Object构造函数
是Function构造函数
的实例,即Function构造函数
的prototype和其 实例Object构造函数
的__proto__指向同一个地方构造函数的__proto__
指向的地方,它的constructor
是此构造函数
- 原型链是
__proto__的路径
Object.prototype
的__proto__指向null
,是原型链终点
原型继承
就是实例
可以使用构造函数上的prototype
中的方法,实例先找自身有没有此方法,没有就沿着原型链找A instanceof B
的作用是判断
B的prototype
是否在A的原型链
上