JavaScript原型篇

JavaScript原型篇

1. 原型:

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

Person.prototype.name = "小张";
function Person(){
	
}
var person = new Person();

这个 person 就是构造函数 Person 生产出来的对象,由于 Person 是函数,函数也属于一种对象,对象就有属性和方法,那么我现在就在上边给 Person 加上一个 prototype 属性,这个 prototype 就是原型,它是系统自带的属性,在这个 Person 函数刚出生的时候,这个 Person.prototype 就被定义好了,Person.prototype 才开始可以把它理解成一个空对象,他就是这个 Person 构造函数构造出对象的祖先,好,现在我们给祖先加一个属性,即 Person.prototype.name = “小张”;那么 person 是 Person.prototype 祖先的晚辈,他就能继承祖先的属性,假如你单纯访问 person 就是一个空对象,但是你访问 person.name 就得到“小张”,他拿的就是祖先的属性,这就叫做继承。什么是公共祖先,假如说我们在下边继续写上 var person1 = new Person(); 这个 person 和 person1 都是 Person 所生产出来的对象,是兄弟俩,所以他们的祖先都是同一个人 Person.prototype,他俩都能拿到 Person.prototype 的属性,你访问 person1.name 也能得到“小张”,所以原型是他构造出对象的共有祖先,他描述的就是继承的关系。

再比如:

Person.prototype.LastName = "王";
Person.prototype.say = funciton (){
	console.log("hehe");
}
function Person(){
	LastName = "张";
}
var person = new Person();
var person1 = new Person();

此时我们调用 person(或 person1).say 都可以调用这个函数,输出 hehe,这属于借用,假如说我们在函数里边写上 this.LastName = “张”;那么访问 person.LastName 就得到 “王”,取近的,自己身上有就拿自己的,没有的话就去祖先那里找。

(2)作用:可以提取共有属性

例1:

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

这么写理论是没有问题,里边选配的可以这么写,但是流程化生产的每一次执行都要执行这三条语句,这就是代码的偶合,我们学完原型就可以用继承的方式把他们提取出来:

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

现在我们来看这个代码,上边的原型就只执行一次,我们表面上访问car得到Car{owner: “张”, color: “red”},但是我们访问 car.carName 也可以得到“BMW”,就是我们可以把一些公有的部分提取到原型里边。其实还可以简单的写,即然原型是空对象, 那么就可以这么来写:

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

(3)原型的增删改查 例如:

Person.prototype.LastName = "张";
function Person(name){
	this.name = name;
}
var person = new Person("三丰");

查:直接访问 Person.LastName 即可。
改:假如说我们直接 person.lastName = “James”,这样是不可以的,他会给 Person自己身上加一个 lastName 等于 James,就是通过对象想操作原型的东西是不可能的,你访问的话自己没有会去原型那里找的,真要改的话就必须 Person.prototype.lastName = “James”;
增删:一样的,如果真要操作原型属性,就必须用 Person.prototype。

(4)constructor

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

例如上边的,我们调用 car.constructor 就得到 function Car( ){ },constructor 的作用就是指向该对象的构造函数,其实他是 Car.prototype 里的一个隐式属性:

Car.prototype = {
	constructor = Car();  //隐式的
}
function Car(){
}
var car = new Car();

但是隐式的属性也可以修改:

Car.prototype = {
	constructor = Person();  
}
function Person(){
}
function Car(){
}
var car = new Car();

这就成了捣乱了,现在我们 car.constructor 就得到 function Person( ){ }

(5)__proto__
这个 __proto__ 到底是干嘛的?例如:

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

此时我们访问 person. __proto__就得到{name: “abc”, constructor: ƒ},而我们只 给原型加 name 了,所以__proto__里边放的就是原型,那么这个__proto__到底是哪里来的?其实是这样的:在我们用 new 来构造这个函数的时候,他会隐式的发生三段式, 第一步就是创建一个 this 空对象,其实并不是空对象,他一上来就有一个属性叫__proto __ :

this = {
	__proto__:Person.prototype;
}

这个__proto__里放的就是 Person.prototype,他的作用就是当你要访问这个对象里的属性的时候,如果对象没有这个属性,他就会通过__proto__指向的这个索引,去找 Person.prototype 身上有没有这个属性,这个__proto__就起到了一个连接的作用,把原型和自己连接在一起。
这个__proto__前后都有,这是一种命名规则,是告诉人们这个属性不要随便动,尽量不要随意更改,但是还是可以更改的:

Person.prototype.name = "abc";
function Person(){
	
}
var obj = {
	name : "sunny"
}
var person = new Person();
person.__proto__ = obj;

最开始我们访问 person.__proto__得到{name: “abc”, constructor: ƒ},但是我们现在 person.__proto__等于obj,再访问 person.name 就得到“sunny”,因为他的原型被修改了,就是通过 Person 构造函数构造出来的对象的原型未必非得是 Person.prototype,它是可以被经过修改的。因为 person 能找到他的原型的根本原因就是__proto__指向,现在我们更改了他的指向,person.__proto__等于 obj,你再访问 person.name 他就会顺着__proto__的指向去找,找到 obj,输出 sunny,那么,person 自此之后就和 Person.prototype 没有任何关系了。

例 2:下列代码执行完之后访问 person.name 是啥?

Person.prototype.name = "sunnny";
function Person(){
}
var person = new Person();
Person.prototype.name = "cherry";

解析:person 自己身上没有 name 属性,他就会通过__proto__找到 Person.prototype,你在下边吧他的 name 值改成 cherry 了,再访问就是 cherry。

例 3:下列代码执行完之后访问 person.name 是啥?

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

解析:此时应该是 sunny,注意后面的 Person.prototype 直接把对象改变了而不是改变原有原型对象上的属性,此时 person.__proto__依然指向原来的对象。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山大王杨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值