JS 原型的含义和使用

1. 定义:原型是function/函数对象(包括构造函数)的一个属性,它定义了函数构造出的对象的公共祖先。通过该函数构造出的对象,可以继承该原型的属性和方法。原型也是对象

对该定义的解释:

所有的function对象都有一个系统自带的prototype属性,翻译过来即“原型”。有这么一个函数function Person(){},function对象Person的prototype属性(即原型)也是一个对象,存在Person.prototype = {...},我们可以把Person.prototype理解为是Person对象的祖先对象(唯一),此后所有Person的实例对象都会继承Person.prototype祖先对象的属性和方法。

范例:

        Person.prototype.name = "haha";//定义Person的祖先对象中的name属性
        Person.prototype.say = function(){//定义Person的祖先对象中的say方法
			console.log("aha");
		}
		function Person(){}
		var person = new Person();
		var person1 = new Person();

在这里插入图片描述
function对象Person的两个实例对象都为空(没有自己的属性和方法) 但都继承了来自祖先的name属性和say方法

function对象Person的实例对象可以同时有自己的属性和方法,也有继承来的属性和方法

		Person.prototype.LastName = "Liu";
		Person.prototype.say = function(){
			console.log("aha");
		}
		function Person(name,age,sex){
			this.name = name;
			this.age = age;
			this.sex = sex;
			
		}
		var person = new Person("zhuzhu",23,"男");

在这里插入图片描述
可以看到function对象Person的实例对象不为空 有自己的属性 同时也有继承来的属性和方法

使用hasOwnProperty方法可以判断该属性或方法是否是只存在于实例对象而不存在于原型对象上

console.log(person.hasOwnProperty("name")); // true
console.log(person.hasOwnProperty("say ")); // false

2.原型的应用

2.1利用原型的特点和概念,可以提取共有属性

源代码:

		function Car(color,owner){
			this.owner = owner;
			this.carName = "BMW";
			this.height = 1400;
			this.lang = 4900;
			this.color = color;
		}
		var car = new Car('red','ls');

每次function对象Car需要创建新的实例对象都会执行下面三行相同的代码

			this.carName = "BMW";
			this.height = 1400;
			this.lang = 4900;

这会造成代码冗余 ,我们可以用原型提取出来,通过继承祖先的属性和方法让每一个创建的Car对象都拥有共有的属性

改进代码:

		Car.prototype.carName = "BMW";
		Car.prototype.height = 1400;
		Car.prototype.lang = 4900;
		function Car(color,owner){
			this.owner = owner;
			this.color = color;
		}
		var car = new Car('red','ls');

在这里插入图片描述

2.2原型的增删改查

		Car.prototype.carName = "BMW";
		Car.prototype.height = 1400;
		Car.prototype.lang = 4900;
		function Car(color,owner){
			this.owner = owner;
			this.color = color;
		}
		var car = new Car('red','ls');

不能通过创建出来的car对象新增原型的属性方法,因为prototype属性是function对象的属性,不是创建出来的car对象的属性
在这里插入图片描述
在这里插入图片描述
可以通过function对象Car调用prototype属性新增原型属性
在这里插入图片描述
在这里插入图片描述

创建的car对象可以通过delete关键字删除自己的属性
在这里插入图片描述
在这里插入图片描述
但创建的car对象不可以通过关键字delete删除原型的属性
在这里插入图片描述
在这里插入图片描述
删除后 返回true(返回true是因为系统认为删除一个不存在的属性也ok)
但原型属性并没有被删去
在这里插入图片描述
function对象的prototype属性可以通过delete关键字实现原型属性的删除
在这里插入图片描述

不能通过创建出来的car对象查看原型的属性方法,因为prototype属性是function对象的属性,不是创建出来的car对象的属性
在这里插入图片描述
用function对象可以查看原型属性方法
在这里插入图片描述

创建的car对象都不能查看原型,自然是更改不了原型属性方法
function对象可以通过prototype属性更改原型属性方法
在这里插入图片描述

3.对象查看对象的构造函数【隐式属性constructor】

		function Car(){}
		var car = new Car();

在这里插入图片描述

在这里插入图片描述
浅粉色字体表示系统隐式地自动创建的属性方法

constructor属性可以被修改

		function Person(name,age,sex){
			this.name = name;
			this.age = age;
			this.sex = sex;
		}
		Car.prototype={
			constructor : Person
		}
		function Car(){}
		var car = new Car();	

在这里插入图片描述

4.对象查看原型 【隐式属性__proto__(前后各两个杠)】

		Car.prototype.name = "kkk"
		function Car(){}
		var car = new Car();

在这里插入图片描述
在代码中我们只给构造函数的原型添加了name属性,由此可知 对象的隐式属性__proto__ 指向的是 其构造函数的原型

相当于

		Car.prototype.name = "kkk"
		function Car(){
		//var this = {
		//	__proto__:Car.prototype
		//}
		}
		var car = new Car();

代码中隐去的过程只会在Person对象被创建时隐式地发生

__proto__属性指向的原型可以被更改

在原有代码基础上添加下面obj对象

		var obj = {
			name:"ff"
		}

在控制台对对象的__proto__属性进行更改,__proto__属性被改变,对象原型也相应的改变
在这里插入图片描述


问题1:代码如下 创建的person对象的name属性是什么?

		Person.prototype.name = "Liu";
		function Person(){}
		var person = new Person();
		Person.prototype.name = "lei";

在这里插入图片描述
这是在原有的原型基础上把name属性改了

换一种写法呢?此时创建的person对象的name属性是什么?

		Person.prototype.name = "Liu";
		function Person(){}
		var person = new Person();
		Person.prototype = {
			name:"lei"
		}

在这里插入图片描述
这是直接把原型给改了,换了个原型对象,为什么呢?

举个简单的例子 便于理解

        //引用值obj指向对象{name:"a"}
        var obj = {name : "a"};
        //引用值obj1指向了引用值obj指向的对象{name:"a"}
        var obj1 = obj;
        //obj改为指向对象{name:"b"} 而原有对象{name:"a"}依旧存在,obj1仍指向原有对象
        obj = {name : "b"} ;

在这里插入图片描述
同样的 回到原问题

		Person.prototype.name = "Liu";
		function Person(){}
		var person = new Person();
		Person.prototype = {
			name:"lei"
		}

在创建一个person对象的时候,发生以下过程

	function Person(){
		//var this = {__proto__ : Person.prototype}
	}

person对象的__proto__和其构造函数Person的prototype属性指向同一空间对象

	Person.prototype = {
		...		
	}

Person.prototype指向另一空间对象,而__proto__仍指向原来的对象
在这里插入图片描述
person.name是从person.__proto__属性中取值,而__proto__仍指向原来的对象,故name属性的值仍为"Liu"

问题2:代码如下 创建的person对象的name属性是什么?

		Person.prototype.name = "Liu";
		function Person(){}
		Person.prototype = {
			name:"lei"
		}
		var person = new Person();

代码的顺序非常重要 会影响程序执行的结果

只有在创建对象的时候,才会在对象中发生var this = {__proto__ : Person.prototype} 这一过程,而在创建对象之前,Person.prototype属性已被改变,指向对象{name:“lei”},故创建的person对象的__proto__属性也指向同一对象{name:“lei”}
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值