JavaScript 原型链篇

(1)比如说:

function Person(){
}
var person = new Person();

此时我们访问 Person.prototype 发现里边还有一个__proto__属性,那就说明,原型还有原型,那我们就来写一写原型连成链的东西:
在这里插入图片描述

GrandFather.prototype.LastName = "杨";
function GrandFather(){
}
var grandFather = new GrandFather();
Father.prototype = grandFather;
function Father(){
	this.name = "haha";
}
var father = new Father();
Son.prototype = father;
function Son(){
	this.age = 18;
}
var son = new Son();

最开始的时候 GrandFather 有一个属性 prototype,GrandFather 是一个构造函数,他构造出了对象 grandFather,然后 grandFather 是这个 Father 构造函数的原型,Father 又构造出对象 father,这 个 father 又是 Son 构造函数的原型,这个 Son 又构造出对象 son,现在我们给 Father 里加上一个 this.name = “haha”;给 Son 里边加上 this.age = 18;,现在我们访问 son.age,自己身上就有,所以得 18,我们接着访问 son.name,自己身上没有就找__proto__,然后指向原型 father,father 里有,所以输出“haha”, 现在我们访问一个高级的,访问 son.lastName,自己身上没有,找到__proto__,然后指向原型 father,father 自己也没有,就继续找,找到自己的__proto__,指向原型 grandFather,grandFather 自己身上依然没有,就找自己的__proto__,指向原型 GrandFather.prototype, 这里找到了 lastName,输出得 “杨”。这个把原型上边再加一个原型再加一个原型…… 形成了一个链,访问顺序是依照链的顺序,我们就把他叫做原型链,原型链的连接点就是__proto__,他的访问顺序和作用域链差不多,可近的来,近的有就访问近的,没有的话再往远处找,找到终端依然没有就输出 undefined。其实我们表面上看 GrandFahter 就是终端了,然而并不是,因为你会发现当你访问 Grand.prototype 的时候里边还有 proto,这个__proto__指向 Object,其实 Object.prototype 才是所有对象的最终原型,是原型链的终端,你在访问 Object.prototype. __proto__就得到 null。比如你访问 son.toString 就得到ƒ toString() { [native code] },他拿的就是 Object.prototype 里的东西。

(2)原型链上的增删改查(接着上个例子讲)

原型链上的增删改查和原型上的增删改查差不多是一致的:
查看:可近的来,近处没有就往远处找,找到终端依然没有就输出 undefined。
删除:通过他的子孙是没办法删除的,但是通过自己可以删,例如:delete Father.prototype.name
修改:除非本人修改,后代是无法修改的。
增加:除非自己增加,后代无法增加。
但是有个特例:现在我给上边的 Father 函数里加点儿东西:

function Father(){
	this.nema = "haha";
	this.fortune = {
		card1 : "visa"
	}
}

现在我们访问 son.fortune 就得到{card1: “visa”},我们修改 son.fortune = 200; 这就等于给son加了一个fortune属性,你访问son得到Son{age: 18, fortune: 200},但是你访问 father.fortune 还是{card1: “visa”},但是现在我不这么改,我不像上边那样去改,我直接 son.fortune.card2 = “master”,现在我访问 son 得到 Son{hobbit: “smoke”},好像 son自己并没有变,我们访问father.fortune得到{card1: “visa”, card2: “master”},但是这种修改是引用值自己的修改,因为你 son.fortune 就相当于 fortune 被你取出来了,取出来之后.name 就相当于 fortune.name 给自己加东西,这不算一种赋值的修改,这算一种调用的修改,这种层面上的修改是可以的, 但是直接给他加值覆盖进去是不行的,这种修改也仅限于引用值,原始值是不可以的。
再比如:

function Father(){
	this.name = "haha";
	this.fortune = {
		card1 = "visa"
	}
	this.num = 100;
}

我们访问 son.num 得到 100,现在 son.num++,我们访问 father.num 还是 100,但是我们访问 son 就是 Son{hobbit: “smoke”, num: 101},++就是自身加 1 赋给自身,son.num = son.num + 1,他先会把 son.num 取出来,再+1 赋给自身,赋值后就变成自己的了。
例:

Person.prototype = {
	name : 'a',
	say : function sayName(){
		console.log(this.name)
	}
}
function Person(){
	this.name = 'b'
}
var person = new Person();

现在我们调用 person.sayName();就会输出 a,那我们现在给 Person 函数里加上 this.name = “b”,在调用 person.sayName();,虽然 sayName 属性是原型里的,但是他里边打印的是 this.name,有一条规定就是谁调用的函数 this 就指向谁,因为是 person 调用的,所以 this 指向 person,输出 b。第一次调用的时候是因为 person 里没有 name 所以输出 a,你如果调用 Person.prototype.sayName()就会输出 a.
又一例:

Person.prototype = {
	height: 100,
	
}
function Person(){
	eat : function(){
		this.height ++;
	}
}
var person = new Person();

我们现在调用 person.eat(),此时访问 Person.prototype 是{height: 100},访问 person 就得到 Person {eat: ƒ, height: 101},这个和上边的是一样的,取出来加 1 赋给自身。

(3)Object.create(原型)

var obj = {};
var obj1 = new Object();

我们来看,第一种创建对象的方法叫做对象字面量,他这么创建出来也是有原型的,原型就是 Object.prototype,在你创建的时候系统就会隐式的加上 new Object,那他和第二种创建的就是一样的了,因为这个 obj1 的原型也是 Object.prototype,所以第二种也没有啥用,而且加东西不好加,所以第二种很少见,在以后开发的时候不能用第二种方法,必须用对象字面量的创建方式。

Person.prototype = {};
function Person(){
}

这个 Person.prototype 默认是一个空对象,也是对象字面量的方法创建的,那么他的原型毋庸置疑就是 Object.prototype。

其实还有一种对象的创建方法:

var obj = {name:'a'};
var obj1 = Object.create(obj);

这样通过Object.create也能创建出对象,括号里放的就是原型,你现在访问obj1.name 就是 a。

考点:阿里巴巴以前有一道判断题说所有的对象最终都继承自 Object.prototype,这么说是不对的,我们前边确实讲的原型的终端都是 Object.prototype,但是有例外,学了 Object.create()就不一样了,这个括号里还必须放东西,不放东西会报错。但是可以放两种值:object(对象)和 null。好,那既然可以放 null,我们就试试:

var obj = Object.create(null);

现在我们访问 obj 得到{ },这是一个真正的空对象,里边啥都没有,所以他没有原型,但他可以当对象来用,比如说加个属性等。我们人为的 obj.proto = {name: “sunny”},你再访问 obj.name 得到 undefined,所以这个__peoto__是系统自带的,可以修改,但是你自己加的系统是不会认得。

结论:绝大多数对象最终都继承自 Object.prototype(并不是所有)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

山大王杨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值