通过对象、构造函数深入理解js原型

说一些题外话

在最近的实习工作中因大量涉及到原生js的编写,因此在工作之余重新拿起红宝书阅读,每重新看一遍都受益匪浅,最近又读到了js中难点原型、原型链,这里仅是本人对js原型的理解和观点,若有槽点错误之处,希望不吝赐教。

接下来我们就直奔主题

怎样创建对象?创建对象方法有几种?

使用构造函数创建对象

var M = function (name) {
 		 this.name = name;
 	 }

这是比较传统创建对象的方法,这里 M 为构造函数,当创建一个构造函数的时候,就为这个构造函数添加了一个 prototype 原型属性表示M的原型对象,而在这个prototype 中自动生成了一个 constructor 构造器指向拥有 prototype 指针的构造函数,而这里就是 M

用如下的UML图便容易理解

M构造函数 原型对象 constructor prototype指针指向 拥有 指向拥有 prototype指针的构造函数 M构造函数 原型对象 constructor
console.log(M.prototype.constructor===M)//true

ok,理解了构造函数与prototype、constructor之间的关系,那么实例与他们之间的关系是如何呢?

var m=new M("Bob");//实例化一个对象 m

当新建一个实例时就为 m 创建了__proto__ 或([[Prototype]]、< prototype >)属性指向构造函数M的原型对象 prototype

实例对象m 原型对象(prototype) M构造函数 constructor 通过 __proto__指针指向 用 prototype 表示 拥有 指向拥有 prototype指针的构造函数 实例对象m 原型对象(prototype) M构造函数 constructor

注意:原型是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);
        })();

这里其实是重写原型,重写原型是在原型链继承方面的知识,
重写原型后还会有一些其他的影响,有兴趣的同学可以去了解了解。

总结

  1. 原型是怎样产生的?
  2. 实例对象、构造函数、proto、prototype互相的联系
  3. 创建对象的几种方式
  4. 原型链的终点是Object.prototype
  5. Array、Function、Object、都是Function 的实例对象
  6. Array.prototype、Function.prototype是Object的实例对象(原型链相关知识)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值