面向对象和原型链的用法(中)

好了,我们看过了一些简单的用法,关于原型链的,下面我来说一些它常用到的模式

首先 我们来 看一下 in这个操作符,它有两个作用 单独使用和 for - in 使用,单独使用的作用是 in会给定对象的属性的返回值,无论是原型还是实例都返回true

function CreateCat() {
}
CreateCat.prototype.name = "小白";
CreateCat.prototype.age = 1;
CreateCat.prototype.color = "白色";
CreateCat.prototype.say = function () {
	alert(this.name);
}
let cat1 = new CreateCat();
let cat2 = new CreateCat();
cat1.name = "小黑";
alert(cat1.name);           		  // 来自于实例 =>小黑
alert(cat2.name);                     // 来自于原型 =>小白
alert(cat1.hasOwnProperty("name"));   // true
alert(cat2.hasOwnProperty("name"));   // false
alert("name" in cat1);   			  // true
alert("name" in cat2);   			  // true

下面我们来说说 Object.keys() 的用法, 可以枚举出对象上的实例

function CreateCat() {
}
CreateCat.prototype.name = "小白";
CreateCat.prototype.age = 1;
CreateCat.prototype.color = "白色";
CreateCat.prototype.say = function () {
	alert(this.name);
}

let keys = Object.keys(CreateCat.prototype);
console.log(keys );     // 结果是 => ["name", "age", "color", "say"]

let cat1 = new CreateCat();
cat1.name = "小黑";
cat1.age=5;
let keyscat1 = Object.keys(cat1);  // 结果是 => ["name", "age"]
console.log(keyscat1);

在上面 我们看到的例子中 每次都要敲 CreateCat.prototype 这个样子很麻烦,那么我们的简单方法是什么呢,原型字面量语法

function CreateCat() {
}
CreateCat.prototype = {
	name:"小白",
	age:1,
	color:"白色",
	say: function () {
		alert(this.name);
	}
};

// 但是这个样子有一个问题,因为我们的每创建一个函数,就会同时创建它的prototype对象和constructor对象,但是我们使用 字面量原型语法,那么constructor不在指向CreateCat 这个对象 ,而是指向了 Object 
let cat = new CreateCat();
alert(cat instanceof Object);       // true
alert(cat instanceof CreateCat);    // true
alert(cat.constructor == Object);   // true
alert(cat.constructor == CreateCat);// false

// 如果你要用到的 constructor 很重要 可以通过这样子来实现
function CreateCat() {
}
CreateCat.prototype = {
	constructor: CreateCat,     // 把CreateCat 赋值给constructor
	name:"小白",
	age:1,
	color:"白色",
	say: function () {
		alert(this.name);
	}
};

let cat = new CreateCat();
alert(cat instanceof Object);       // true
alert(cat instanceof CreateCat);    // true
alert(cat.constructor == Object);   // false     不在是Object 了
alert(cat.constructor == CreateCat);// true   我们可以看到已经指向了CreateCat

我们来看一下 如果在最开始 我们添加最原始的执行,那么它将切断原型链之间的关系

function CreateCat() {
}
// 当构造函数指向最初的原型prototype指针,那么它将切断原型链之间的关系
let cat = new CreateCat();
CreateCat.prototype = {
	constructor: CreateCat,     // 把CreateCat 赋值给constructor
	name:"小白",
	age:1,
	color:"白色",
	say: function () {
		alert(this.name);
	}
};

cat.say();   // 结果是 => cat.say is not a function

在原型中很多实例是被共享的,那么一个引用类型,会发生什么事情呢,请看例子

function CreateCat() {
}
CreateCat.prototype = {
	constructor: CreateCat,     // 把CreateCat 赋值给constructor
	name:"小白",
	age:1,
	color:"白色",
	friends: ["小红", "小绿"],
	say: function () {
		alert(this.name);
	}
};

let cat1 = new CreateCat();
let cat2 = new CreateCat();

// 给cat1 实例上添加一个朋友
cat1.friends.push("小黑");
console.log(cat1.friends);   //结果是 => ["小红", "小绿", "小黑"]
// 什么 cat2上面的实例 也被影响了,因为原型链上是共享的,所以在引用类型上,是一样的,这明显不是我们想要的
console.log(cat2.friends);   //结果是 => ["小红", "小绿", "小黑"]  
console.log(cat1.friends == cat2.friends)   // true

那么我们的解决方案是什么呢
我们使用 构造模式 和 原型模式,把要影响的放入到 构造函数中,通用的方法,放入到原型对象中,请看下面的例子

function CreateCat(name, age, color) {
	this.name = name;
	this.age= age;
	this.color = color;
	this.friends = ["小红", "小绿"];
}
CreateCat.prototype = {
	constructor: CreateCat,     // 把CreateCat 赋值给constructor
	say: function () {
		alert(this.name);
	}
};

let cat1 = new CreateCat("小黑", 2, "黑色");
let cat2 = new CreateCat("小白", 1, "白色");

// 现在我们往cat1的 实例中添加小黄
cat1.friends.push("小黄");
console.log(cat1.friends);                  // ["小红", "小绿", "小黄"]
console.log(cat2.friends);                  // ["小红", "小绿"]
console.log(cat1.friends === cat2.friends); // false
console.log(cat1.say === cat2.say);         // true

寄生构造函数模式

function CreateCat(name, age, color) {
	let cat = new Object();
	cat.name = name;
	cat.age= age;
	cat.color = color;
	cat.say = function () {
		console.log(this.name);
	}
	return cat;
}

let cat1 = new CreateCat("小白", 2, "白色");
cat1.say();     // 结果是 => 小白
console.log(cat1 instanceof CreateCat);	   // false 与原型和实例都没有关系
console.log(cat1 instanceof Object);		   // true
// 这中模式 返回的对象 和 构造函数的原型属性没有任何 关系,所以有其他模式的话,不要使用这种模式

如果想更深一步的了解,请参考博客
面向对象和原型链的用法(上)

面向对象和原型链的用法(下)

好了,有什么问题欢迎指出哦,一起进步,哈哈哈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值