对象的创建方法
//第一种
// 创建对象的三种方法
let o1 = {
name: "德玛西亚"
}
let o11 = new Object({
name: "诺克萨斯"
})
//第二种
let M = function(name) {
this.name = name
}
let o2 = new M("艾欧尼亚")
//第三种
let p = {
name: '班德尔城'
}
let o3 = Object.create(p)
console.log(o1)
console.log(o11)
console.log(o2)
console.log(o3)
输出的结果为

可以看到第三种只输出了一个空对象,原因后面补上。
原型,构造函数,实例,原型链
首先我们来看看一张图,这是慕课上一位老师讲解原型链时用到的图片。

构造函数
任何被 new引用到的函数都可以叫做构造函数
let M = function(name) {
this.name = name
}
let m = new M('nimeia')
//上面的m是用new创建出来的,new引用了M(),所以M()就是一个构造函数
原型对象
当一个构造函数被new所引用的时候,js引擎会创建一个原型对象。为构造函数加上一个prototype属性,这个属性指向的就是原型对象。
实例
实例就是构造函数创建出来的对象。
let M = function() {
console.log('demo')
}
console.log(M.prototype)
//输出
//{
// constructor: ƒ (name)
//__proto__: Object
//}
//上面就是一个原型对象,constructor是构造器,返回构造函数
console.log(M.prototype.constructor === M) //输出为true
let m = new M()
console.log(m.__proto__ === M.prototype) //输出 true
原型链
原型链就是从实例对象往上找创建实例的原型对象,原型对象又继续往上找创建该原型对象的原型对象,直到找到object.prototype为止。这就是原型链。如果我们修改原型对象的时候,所有该原型对象创建出来的实例都可以公用这些新属性。
let M = function(name) {
this.name = name
}
let o1 = M('你妹啊')
M.prototype.say = function () {
console.log(this.name)
}
let o2 = new ('你大爷')
console.log(o1.say()) //输出 你妹啊
console.log(o2.say())//输出 你大爷
ps:函数也是对象
console.log(M.__proto__ === Function.prototype) //输出true
instanceof
判断实例对象的proto属性跟构造函数的prototype属性是否引用同一个地址。但是又一个问题就是在同一条原型链上的构造函数都可以被instanceof看做实例对象的一个实例,这样就不严谨。
let M = function() {}
let m = new M()
console.log(m instanceof M) //输出true
console.log(m instanceof object) //输出也是true
//这是因为
m.__proto__ === M.prototype //true
M.prototype.__proto__ === Object.prototype //true
//所以m跟object在同一条原型链上,Object被instanceof也看做m的构造函数
所以要找实例的构造函数,可以通过m.__proto__.constructor
来判断
new运算符原理
- 一个新对象被创建。它继承自foo.prototype。
- 构造函数返回一个对象。在执行的时候,相应的传参会被传入,同时上下文(this)会被指定为这个新的实例。new foo等同于new foo(), 只能用在不传递任何参数的情况
- 如果构造函数反悔了一个对象,那个这个对象会取代整个new出来的结果。如果构造函数没有返回对象,那个new出来的结果为步骤1创建的对象。
//模拟new运算符的操作
var new = function (func) {
var o = Object.create(func.prototype); //创建对象
var k = func.call(o); //改变this指向,把结果付给k
if (typeof k === 'object') { //判断k的类型是不是对象
return k; //是,返回k
} else {
return o; //不是返回返回构造函数的执行结果
}
}
//验证
let m = new(M)
console.log(m instanceof M) //true
console.log(m instanceof Object) //true
console.log(m.__proto__.constructor === M) //true
M.prototype.say = function() {
console.log('hello')
}
console.log(m.say()) //hello
上面还遗留了一个问题
就是为啥
let p = {
name: '你妹啊'
}
let o1 = Object.create(p)
console.log(o1)
输出的是一个空对象的问题。
因为用object.create创建的对象都是对原型的引用。
consolo.log(o1.__proto__ === p) //输出true
网友评论