首先上代码
function fs () {
this.name = '哈哈'
fs.say = function () {
console.log('i am ' + this.name)
}
}
var cc = new fs()
console.log(cc)
console.log(cc.p)
cc.say()
image.png
这里我们首先创建了一个构造函数,配合上new关键字,看看new到底做了啥
function fs () {
//1.创建一个新对象,赋予this,这一步是隐性的,
// let this = {};
//2.给this指向的对象赋予构造属性
this.name = '哈哈'
fs.say = function () {
console.log('i am ' + this.name)
}
//3.如果没有手动返回对象,则默认返回this指向的这个对象,也是隐性的
// return this;
}
接下来再解释一下上面执行结果是为什么
console.log(cc) //输出cc对象
console.log(cc.p) //cc并没有p这个属性所以undefined
cc.say() //cc也没有say这个方法所以报错,say不是个函数
至于为什么,我们打开cc这个对象看看
可以看到,cc这个对象除了有一个name属性之外,他的原型对象上并没有任何其他东西了,我们都知道,js在访问一个对象的属性或者方法的时候,会沿着原型链一层一层的去找,也就是proto这个对象,如果这个对象身上没有,又会在proto对象的proto属性身上去找,一直到最大的boss object身上,如果都没找到就会返回null,返回null的原因也很简单,因为大boss的原型指向的就是null
这里就涉及到了原型链和原型对象,原型对象也分为显式原型对象和隐式原型对象
proto就是隐式原型对象 而还有一个prototype则是显式原型对象
在js中万物皆对象,函数其实也是个对象,只不过他比较特别,他不但有proto这个属性,他还有一个prototype属性
一个对象的proto其实是指向他的构造函数的prototype原型的 接下来再看一个例子
function fs () {}
fs.prototype.p = 1
fs.prototype.say = function(){
console.log('i am' + this.p)
}
var cc = new fs()
console.log(cc)
console.log(cc.p)
cc.say()
image.png
这次我们在构造函数的原型对象prototype上添加了一个属性p=1 say=一个函数
这一次我们在打开cc这个对象的proto属性可以看到,诶!有p 还有say这个函数
所以打印的话也没有问题,正确的输出了
至于这个constructor暂时还没有搞明白是个咋回事,
cc的原型链是 proto --> fs.prototype --> object.proto
网友评论