创建对象的几种方法
第一种方式:字面量对象
var o1 = {name:'o1'};
var o2 = new Object({name:'o2'});
理解字面量,默认原型链指向Object
第二种方式:通过显式构造函数
var m = function(name){
this.name = name;
}
var o3 = new M('o3');
第三种方式:Object.create
var p = {name: 'p'};
var o4 = Object.create(p);
在控制台输入o1, o2, o3, o4
o1, o2 输出一个Object对象
o3是一个M对象
o4是个空对象
o1, o2, o3, o4 均有name属性
原型、构造函数、实例、原型链
- o1, o2, o3 为实例
- 构造函数:任何一个函数只要被new操作了,就可以被叫做构造函数
- 函数都有prototype属性,指的是原型对象(初始化空对象)
- 原型对象怎么区分是被哪一个构造函数引用:constructor
- 对象是一个实例
上面的例子中o3是实例,M是构造函数
//构造函数和原型对象的关系
M.prototype.constructor === M
true
//实例和原型对象之间的关系
o3.__proto__ === M.prototype
true
原型链:从一个实例对象向上找构造这个实例的相关联的对象,再往上找,有创造它的原型对象,一直类推,到Object.prototype终止(整个原型链的顶端),原型链通过prototype
和__proto__
属性进行向上查找。

原型对象和原型链之间起的作用:构造函数中增加很多属性和方法。当有多个实例,共用一个方法,不能拷贝多次(若每个实例都要拷贝一份,会占内存,没有必要),所以有相同的方法要考虑存到共同的东西上,这个共同的东西就是原型对象。这就是js引擎支持的原型链的功能,任何一个实例对象通过它的原型找到它上面的原型对象,上面的实例和方法可以被共享。
var M = function(name){this.name = name;};
M.prototype.says = function() {
console.log('say hi');
}
var o5 = new M('o5');
控制台输出:
o3.say()
say hi
o5.say()
say hi
注意:
-
函数才会有prototype
-
函数即是函数也是对象,也有
__proto__
属性例:写一个表达式说说原型是什么
-
M.__proto__ === Function.prototype
返回true
Object是个构造函数,原型为
Function.prototype
-
Array
构造函数的原型:Array.prototype
-
instanceof 原理
原理:实例对象的__proto__
属性和构造函数没什么关联,其实是引用的原型对象。判断实例对象的属性和构造函数的属性是不是同一个引用。
原型对象上可能还会有原型链,用实例对象instanceof判断原型的构造函数,这条原型链上的函数返回都是 true
o3 instanceof M
true
//只要是原型链上都可以看作instanceof的构造函数
o3 instanceof Object
true
解释:
o3.__proto__=== M.prototype
true
M.prototype.__proto___=== Object.prototype
true
o3.__proto__.constructor === M
true
o3.__proto__.constructor === Object
false
new运算符
工作原理:
-
后面加上构造函数,一个新对象被创建,它继承自构造函数原型对象foo.prototype
-
构造函数foo被执行,执行的时候,相应的传参会被传入,同时上下文(this)会被指定为这个新实例。new foo 等同于 new foo(),只能用在不传递任何参数的情况。
-
如果构造函数返回了一个“对象”,那么这个对象会取代整个new出来的结果,如果构造函数没有任何返回对象,那么new出来的结果为步骤1创建的新对象。有返回对象,直接返回构造函数。
实现一个new运算符效果:
var new2 = function(func){
var o = Object.create(func.prorotype);
//执行构造函数
var k = func.call(o);
if(typeof k === 'object'){
return k;
} else {
return o;
}
}
控制台输出:
o6 = new2(M)
o6 instanceof M
true
o6 instanceof Object
true
o6.__proto__.constructor === M
true
M.prototype.walk = function() {
console.log('walk')
}
o6.walk()
walk
o3.walk()
walk
为什么o4直接拿不到name属性
Object.create方法创建的对象是用原型链连接的
o4.__proto__ === p
true
总结:原型链真的很重要,值得反复理解推敲。
网友评论