文章目录
说一些题外话
在最近的实习工作中因大量涉及到原生js的编写,因此在工作之余重新拿起红宝书阅读,每重新看一遍都受益匪浅,最近又读到了js中难点原型、原型链,这里仅是本人对js原型的理解和观点,若有槽点错误之处,希望不吝赐教。
接下来我们就直奔主题
怎样创建对象?创建对象方法有几种?
使用构造函数创建对象
var M = function (name) {
this.name = name;
}
这是比较传统创建对象的方法,这里 M 为构造函数,当创建一个构造函数的时候,就为这个构造函数添加了一个 prototype 原型属性表示M的原型对象,而在这个prototype 中自动生成了一个 constructor 构造器指向拥有 prototype 指针的构造函数,而这里就是 M
用如下的UML图便容易理解
console.log(M.prototype.constructor===M)//true
ok,理解了构造函数与prototype、constructor之间的关系,那么实例与他们之间的关系是如何呢?
var m=new M("Bob");//实例化一个对象 m
当新建一个实例时就为 m 创建了__proto__ 或([[Prototype]]、< prototype >)属性指向构造函数M的原型对象 prototype
注意:原型是m与M的prototype之间的联系,不是m与M之间的联系,换句话说构造函数与实例对象没有直接关系
因此我们可以得出 实例对象的__proto__严格相等于 构造函数的 prototype对象
console.log(m.__proto__===M.prototype) // true
console.log(m.constructor===M) // true
现在你理解了原型的概念了吗? 如果还不太理解就继续往下看…
函数M实际上也是Function类型的一个实例
这里函数M是一个构造函数只是因为是大写的M,用来区分普通的函数,但实际上他们没什么实质性的区别。
所以函数M实际上也是Function类型的一个实例
//Function参数列表所有参数都为字符串类型,最后一个字符串内容是要执行的函数代码,其余字符串为数量
// var functionname = new Function( [argname1, [... argnameN,]] body );
var M=new Function("name","this.name=name");
既然M也是一个实例对象,那么它也有__proto__ 指向 它的构造函数的prototype 因此我们可以得出:
console.log(M.__proto__===Function.prototype); //true
console.log(M.constructor===Function); //true
console.log(Function.prototype.constructor===Function); //true
那么 Function 有__proto__ 属性吗?
显然是有的,
我们可别忘了函数也是一个对象,函数有自己的属性和方法,因此你能说它不满足对象的概念吗?
所以Function 也是 Object 的一个 实例对象吗?
答案是错误的。
前面我们说过谁是谁的实例对象就有__proto__ 指向它的构造函数的prototype
console.log(Function.constructor === Object) // false
console.log(Function.__proto__===Object.prototype); // fasle
console.log(Function.constructor === Function) // true
console.log(Function.__proto__===Function.prototype); // true
为什么会这样?
首先Function 不是 Object 的一个 实例对象,
Function 还是Function 的实例对象
(Array、Function、Object 都是 Function 实例对象)
因此都有
console.log(Array.__proto__===Function.prototype) //true
console.log(Function.__proto__===Function.prototype) //true
console.log(Object.__proto__===Function.prototype) //true
而 Array、Function的 prototype 原型对象 才是 Object的 实例对象
既然 Function.prototype 是Object的实例对象 必然有__proto__ 指向构造函数的prototype
console.log(Function.prototype.__proto__=== Object.prototype) // true
console.log(Object.prototype.constructor===Object); // true
这就是我下一篇要讲的原型链、继承的概念
接下来还有一个疑问,Object有没有__proto__ (原因前面已经讲过) 噢不是 是
Object.prototype 有没有__proto__?
答案是没有的
console.log(Object.prototype.__proto__) //null
这就是原型链的终点,也是每一个实例对象原型的终点。
好现在我们已经了解了原型是怎样产生的,并且具有什么的特点,它与构造函数和实例对象之间的联系
m的构造函数是M
m.proto===M.prototype
M的构造函数是Function
M.proto===Function.prototype
Function的构造函数是Function
Function.proto===Function.prototype
Function.prototype的构造函数是Object
Function.prototype.proto===Object.prototype
Object的构造函数是Function
Object.proto===Function.prototype
Object的prototype没有构造函数没有__proto__
Object.prototype.proto===null
我们得出结论:
只有实例对象才有__proto__ 属性,只有构造函数才有ptototype对象 且实例对象的__proto__指向构造函数的prototype
如果既是构造函数又是另一个构造函数的实例对象,那么同时拥有__proto__ 和 prototype
使用对象字面量创建对象
var o = {
name: "ojbk",
age: 22
}
使用对象字面量创建对象是一种最常用的创建对象的方法,
前面我们说过当创建对象的时候就为添加__proto__ 指向构造函数的prototype
console.log(o.__proto__===Object.prototype); //true
console.log(Object.prototype.constructor===Object); //true
其实这里本身就是对Object的一个实例对象
o2 = new Object({
ok: 'ok',
no: 'no'
})
console.log(o2.__proto__===Object.prototype); //true
console.log(Object.prototype.constructor===Object); //true
说到这儿相信同学们都理解了原型的基本概念了
其实还有一种创建对象的方法,
使用Object.create()创建对象
这种方法其实用在继承方面较多,不过也是创建对象的一种简便方法
// 通过Object.create()方法创建对象
(function () {
var OP = {
pname: "pname",
page: '22'
}
// 使用此方法强制把p.__proto__属性指向OP对象 注意是OP对象 而不是OP.prototype
// OP对象没有prototype属性 只有构造函数才有prototype对象
// 因为Object是OP对象的构造函数,OP是Object的实例 因此Object才有prototype对象
var p = Object.create(OP);
console.log(p.constructor === OP); //false
console.log(p.__proto__ === OP); //true
console.log(p.constructor === Object); //true
console.log(OP.constructor === Object); //true
// OP是Object的实例 只有实例对象才有__proto__属性
//且指向构造函数的prototype 原型对象
console.log(OP.__proto__ === Object.prototype);
})();
这里其实是重写原型,重写原型是在原型链继承方面的知识,
重写原型后还会有一些其他的影响,有兴趣的同学可以去了解了解。
总结
- 原型是怎样产生的?
- 实例对象、构造函数、proto、prototype互相的联系
- 创建对象的几种方式
- 原型链的终点是Object.prototype
- Array、Function、Object、都是Function 的实例对象
- Array.prototype、Function.prototype是Object的实例对象(原型链相关知识)