JS三座金山
JS三座金山之——原型与原型链
目录
二、prototype、__proto__与constructor
1.一般来说,构造函数中的prototype与其实例对象中的__proto__是指向同一个地方,这个地方就叫做原型对象。
function Object()其实也是个函数,所以他是Function构造函数的实例
function Function()其实也是个函数,所以他也是Function构造函数的实例
前言
相信大家都听过前端的三座大山:闭包,原型链,作用域,今天我们来说一下第一座金山——原型与原型链。
一、Function与Object
在此之前先铺垫一些函数与对象的内容。
Function
定义函数
一般来说我们平时定义函数无非以下几种:
const fn1 = function (name, age) {
console.log(`fn1中的name:${name},fn1中的age${age}`);
}
fn1('JAVIS_L', 18)//fn1中的name: JAVIS_L, fn1中的age18
function fn2(name, age) {
console.log(`fn2中的name:${name},fn2中的age${age}`);
}
fn2('JAVIS_L', 18)//fn2中的name: JAVIS_L, fn2中的age18
const fn3 = (name, age) => {
console.log(`fn3中的name:${name},fn3中的age${age}`);
}
fn3('JAVIS_L', 18)//fn3中的name: JAVIS_L, fn3中的age18
说到底,他们的本质都是一样的(只考虑函数声明),都可以使用 new Function来声明。
const fn1 = new Function('name', 'age', 'console.log(`我是fn1中的name:${name},age:${age}`)')
fn1('JAVIS_L', 18)//我是fn1中的name: JAVIS_L, fn1中的age18
const fn2 = new Function('name', 'age', 'console.log(`我是fn2中的name:${name},age:${age}`)')
fn2('JAVIS_L', 18)//我是fn2中的name: JAVIS_L, fn2中的age18
const fn3 = new Function('name', 'age', 'console.log(`我是fn3中的name:${name},age:${age}`)')
fn3('JAVIS_L', 18) //我是fn3中的name: JAVIS_L, fn3中的age18
构造函数
那什么是构造函数呢?俗话说就是,可以用来new
的函数就叫构造函数,箭头函数不能用来当做构造函数。
function Person(name, age) {//这个就是构造函数
this.name = name
this.age = age
}
const p1 = new Person('JAVIS_L',18)//构造函数Person的实例
const p2 = new Person('JARVIS_L',20)//构造函数Person的实例
Object
创建对象
咱们平常开发中,创建一个对象,通常会用以下几种方法。
构造函数创建对象
,他创建出来的对象都是此Function构造函数
的实例,所以这里不讨论它字面量创建对象
new Object创建对象
Object.create创建对象
,创建出来的是一个空原型的对象,这里不讨论它
// 第一种:构造函数创建对象
function Person(name, age) {
this.name = name
this.age = age
}
const person1 = new Person('JAVIS_l', 18)
console.log(person1) // Person { name: 'JAVIS_l', age: 18 }
// 第二种:字面量创建对象
const person2 = { name: 'JAVIS_l', age: 18 }
console.log(person2) // { name: 'JAVIS_l', age: 18 }
// 第三种:new Object创建对象
const person3 = new Object()
person3.name = 'JAVIS_l'
person3.age = 18
console.log(person3) // { name: 'JAVIS_l', age: 18 }
// 第四种:Object.create创建对象
const person4 = Object.create({})
person4.name = 'JAVIS_l'
person4.age = 18
console.log(person4) // { name: 'JAVIS_l', age: 18 }
事实上,字面量创建对象本质上就是new Object创建对象,所以
// 字面量创建对象
const person3 = { name: 'JAVIS_l', age: 18 }
console.log(person3) // { name: 'JAVIS_l', age: 18 }
本质上是
// new Object创建对象
const person3 = new Object()
person3.name = 'JAVIS_l'
person3.age = 18
console.log(person3) // { name: 'JAVIS_l', age: 18 }
Function与Object之间的关系
上面已经说过了构造函数,所以我们常说
- 函数是Function构造函数的实例
- 对象是Object构造函数的实例
那Function构造函数
和Object构造函数
他们两个又是谁的实例呢?
function Object()
其实也是个函数,所以他是Function构造函数
的实例function Function()
其实也是个函数,所以他也是Function构造函数
的实例,没错,他是他自己本身的实例(在下面原型中验证)
二、prototype、__proto__与constructor
- prototype:显式原型(存在于构造函数中)
- __proto__:隐式原型(存在于实例对象中)
prototype、__proto__二者的关系
首先它们两个都叫做原型。一般来说,构造函数中的prototype与其实例对象中的__proto__是指向同一个地方,这个地方就叫做原型对象。
可以验证一下
function Person(name, age) {//构造函数Person
this.name = name
this.age = age
}
// 为构造函数Person的原型对象上添加一个sayName方法
Person.prototype.sayName = function () {
console.log(this.name);
}
console.log(Person.prototype);//{sayName: ƒ, constructor: ƒ}
const person1 = new Person('JAVIS_L', 18)//构造函数Person的一个实例对象person1
console.log(person1.__proto__);//{sayName: ƒ, constructor: ƒ}
console.log(Person.prototype === person1.__proto__);//true
重点来啦!!构造函数中的prototype与其实例对象中的__proto__是指向同一个地方,这个地方就叫做原型对象。
刚刚有两句话大家还记得吗?
- 函数是Function构造函数的实例
- 对象是Object构造函数的实例
下面我们就来分别验证一下。
函数是Function构造函数的实例。还是那句话,构造函数中的prototype与其实例对象中的__proto__是指向同一个地方,这个地方就叫做原型对象。所以这里的fn1、fn2、fn3其实也都是Function构造函数的实例对象。
const fn1 = function (name, age) {
console.log(`fn1中的name:${name},fn1中的age${age}`);
}
fn1('JAVIS_L', 18)//fn1中的name: JAVIS_L, fn1中的age18
function fn2(name, age) {
console.log(`fn2中的name:${name},fn2中的age${age}`);
}
fn2('JAVIS_L', 18)//fn2中的name: JAVIS_L, fn2中的age18
const fn3 = (name, age) => {
console.log(`fn3中的name:${name},fn3中的age${age}`);
}
fn3('JAVIS_L', 18)//fn3中的name: JAVIS_L, fn3中的age18
console.log(Function.prototype === fn1.__proto__);//true
console.log(Function.prototype === fn2.__proto__);//true
console.log(Function.prototype === fn3.__proto__);//true
对象是Object构造函数的实例。还是那句话,构造函数中的prototype与其实例对象中的__proto__是指向同一个地方,这个地方就叫做原型对象。所以这里的person1、person2其实也都是Object构造函数的实例对象。
const person1 = { name: 'JAVIS_L', age: 18 }
const person2 = new Object()
person2.name = 'JAVIS_L'
person2.age = 18
console.log(Object.prototype === person1.__proto__) // true
console.log(Object.prototype === person2.__proto__) // true
下面我们来验证这两句话
function Object()
其实也是个函数,所以他是Function构造函数
的实例function Function()
其实也是个函数,所以他也是Function构造函数
的实例,没错,他是他自己本身的实例(在下面原型中验证)
console.log(Object.__proto__ === Function.prototype) // true
console.log(Function.__proto__ === Function.prototype) // true
constructor
constructor和prototype是成对的,相互指向。
function fn() { }
console.log(fn.prototype) // {constructor: fn}
console.log(fn.prototype.constructor === fn) // true
三、原型链
在此之前我们先验证一个东西:“构造函数Function的原型对象是构造函数Object的实例对象。”对不对呢?我们可以先来验证下
console.log(Function.prototype.__proto__ === Object.prototype) // true
结果是true。为什么呢?????
首先Function.prototype是构造函数Function的原型对象,既然是“对象”,那本质上都是通过new Object()创建的,因此Function.prototype就是Object的一个实例对象,所以Function.prototype的__proto__指向Object.prototype(Person.prototype同理)
原型链
什么是原型链呢?其实俗话说就是:__proto__的路径就是原型链
原型链终点
虽然说三条原型链都指向了Object.prototype,那么原型链的终点就是Object.prototype了么??其实不是的,Object.prototype也有一个__proto__属性,最终指向null!!
至此原型与原型链就讲完了!
四、原型继承
说到原型,就不得不说下原型继承了,原型继承说的就是实例对象可以使用构造函数上prototype中的方法。
function Person(name, age) {//构造函数Person
this.name = name
this.age = age
}
Person.prototype.Introduce = function () {//Person的原型对象
console.log(`我叫${this.name},我的年龄是:${this.age}`);
}
const person1 = new Person('JAVIS_L', 18)//Person的实例对象
// 实例对象使用原型对象中的方法
person1.Introduce()//我叫JAVIS_L,我的年龄是:18
五、例子
var foo = {},
F = function () { };
Object.prototype.a = 'value a';
Function.prototype.b = 'value b';
console.log(foo.a);
console.log(foo.b);
console.log(F.a);
console.log(F.b);
答案
console.log(foo.a);//value a
console.log(foo.b);//undefined
console.log(F.a);//value a
console.log(F.b);//value b
六、 总结
1.一般来说,构造函数中的prototype与其实例对象中的__proto__是指向同一个地方,这个地方就叫做原型对象。
2.
-
函数是Function构造函数的实例
-
对象是Object构造函数的实例
3.
-
function Object()
其实也是个函数,所以他是Function构造函数
的实例 -
function Function()
其实也是个函数,所以他也是Function构造函数
的实例