JavaScript原型链详解

本文讲解JS的原型和原型链。JavaScript是如何通过一个构造函数生成对象实例的?JavsScript是如何读取对象的属性的?

1、构造函数

通常用构造函数来创建具有一定统一性的对象。可以通过new操作符创建一个实例对象。

/*
	工厂生产酸奶可以分成三部;
	1、原料 2、加工 3、出厂
	【注】满足上述三个步骤的函数,我们把它叫做工厂函数。
	在JavaScript中我们可以创建和使用这样的构造函数来创建具有一定的统一性的对象。
*/
	function Person(name, sex){
		//1、原料
		// var person = new Object();
		//this = new Object();
		//2、加工
		//添加属性和方法
		this.name = name;
		this.sex = sex;
		this.showName = function(){
			alert("我叫" + this.name);
		} 

		this.showSex = function(){
			alert("我是" + this.sex + "的");
		}

		//3、出厂
		// return person;
		//return this;
	}

	var p1 = new Person("blue", "男");
	p1.showName(); //我叫blue
	p1.showSex(); //我是男的

	var p2 = new Person("red", '女');
	p2.showName(); //我叫red
	p2.showSex();; //我是女的

	alert(p1.showName == p2.showName); //false
2、实例

通过构造函数生成的对象就叫做实例。上面例子的 p1p2 都是通过 Person() 这个构造函数。当使用构造函数new一个实例的时候,这个函数里面的this指向当前创建的新对象。上面例子中,第一步原料和第三部出场被注掉的原因就是,当时用 new 调用函数的时候,JS会自动完成1、3两步操作。

使用new操作符创建对象的过程:第一步,创建一个新对象。第二步,将构造函数的 this 指向这个新创建的对象(这样就相当于把构造函数的作用域赋给了新对象)。第三步,执行这个构造函数的代码,继承属性。第四步,返回一个新的对象。

3、原型(prototype

每一个构造函数都有一个 prototype 属性,这个属性指向一个对象,这个对象就是通过这个构造函数创建的实例的原型。

每一个 JavaScript 对象(或者说实例, null除外)在创建的时候都会和 prototype 指向的对象相关联,并从上面继承属性。

/*
	【注】如果我们想给一类的对象,添加方法,那么我们可以通过原型prototype,
	将这个方法添加给这个对象的构造函数。
*/
Array.prototype.sum = function(){
	var res = 0;
	for(var i = 0; i < this.length; i++){
		res += this[i];
	}
	return res;
} 
var arr1 = [10, 20, 30, 40, 50];
var arr2 = [1, 2, 3, 4, 5];
alert(arr1.sum());
alert(arr2.sum());

alert(arr1.sum === arr2.sum); //true
4、原型链

既然每一个JS对象在创建的时候都会关联一个原型对象,而且原型对象也是一个JS对象,所以原型对象在创建的时候也同样会关联一个原型对象的原型对象。这样一层层的追根溯源,就形成了一条原型链。

用上面的例子解释就是, arr1 的原型是Array的 prototype 属性,而Array的 prototype 属性指向的也是一个对象,这个对象也是某一个构造函数的实例(比如Object()),所以Array的 prototype 属性指向的对象(即arr1的原型)也会有一个原型,它的原型就是生成它的构造函数的prototype属性。这样一条原型链就生成了。

“继承”的说法。众所周知,对象会继承构造函数的属性,但是此继承非彼继承,原因就是,他并不是真正的继承,而是在创建的对象和构造函数之间会建立一种关联,这些关联组成一个集合,我们现在可以把这个集合理解成原型链,对象与构造函数的原型都是在这条长长的原型链上,它们一环扣一环,当我们在访问某一个对象的属性的时候,首先判断的是这个对象的直接挂载属性有没有,如果没有就会去原型链的上一环(也就是该对象的__proto__)寻找这个属性,如果还没有就会继续访问当前环的上一环,知道找到这个属性或者是走到这个链子的尽头为止。

访问属性,会一环一环的向上查找,但是原型链不是无限长的,它的终点就是Object.prototype。因为Object.prototype的下一环是null

alert(Object.prototype.__proto__ === null) // true

当访问到Object.prototype还没有找到该属性的时候,就会报错undefined

5、__proto__

每一个 JavaScript 对象(或者说实例, null除外)都有一个属性,即__proto__,它指向的就是该对象的原型(即生成该对象的构造函数的 prototype 属性)。

alert(arr1.__proto__ == Array.prototype) //true

既然实例的属性都是继承自构造函数,那么所有的对象都有的属性__proto__是承自哪里呢?嘿嘿,既然是所有的对象都有的属性,当然是承自Object.prototype

与其说是一个属性,不如说是一个 getter/setter,当使用 obj.proto 时,可以理解成返回了 Object.getPrototypeOf(obj)。

6、constructor

constructor的英文意思是构造器,每一个原型都会有这么一个属性指向与之相关联的构造函数。

alert(Array == Array.prototype.constructor) //ture

附图一张:
在这里插入图片描述
(蓝色的线就是一条原型链)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值