JavaScript中的原型

JavaScript中的原型

JavaScript中得到对象的方法

第一种方法:通过new Object得到

var person = new Object();
person.name = "xiaobao";
person.age = 18;
person.sex = "男";
person.say = function(){
	console.log(this.name+this.age+this.sex);
}
person.say();
这种方法,当定义多个person的时候太麻烦

第二种方法:通过json得到

var person = {
	"name" : "xiaobao",
	"age" : 18,
	"sex" : "男",
	"say" : function(){
		console.log(this.name+this.age+this.sex);
	}
}
person.say();

这种方法也是,当定义多个person的时候太麻烦

第三种方法:使用工厂模式
function createPerson(name,age,sex){
	var person = new Object();
	person.name = name;
	person.age = age;
	person.sex = sex;
	person.say = function(){
		console.log(this.name+this.age+this.sex);
	}
	return person;
}
var person1 = createPerson("xiaobao",18,"男");
person1.say();

这种方法可以通过传递参数的方式可以定义多个person,但是对于得到的对象却不知道是什么类型

第四种方法:使用构造函数
function Person(name,age,sex){
	this.name = name;
	this.age = age;
	this.sex = sex;
	this.say = function(){
		console.log(this.name+this.age+this.sex);
	}
}
var person1 = new Person("xiaobao",18,"男");
person1.say();
console.log(person1 instanceof Person);

这种方法实际上跟工厂模式一样,不同之处只是先定义一个Person所谓的类,再用new的方法来创建一个一个的对象,但是 say方法在每个对象创建后都存在了 个方法拷贝( 但是我们 发现代码在只有调用时,say方法才会在堆中创建),这样就增加了 内存的消耗了,如果在对象中有大量的方法时,内存的消耗 会高,这样不行了 。简单地说就是因为say方法是一个闭包函数,每次 创建一个对象,say方法就会多一个,占用的内存会越来越多。

function Person(name,age,sex){
	this.name = name;
	this.age = age;
	this.sex = sex;
	this.say = say;
}
function say(){
	console.log(this.name+this.age+this.sex);
}
var person1 = new Person("xiaobao",18,"男");
person1.say();
console.log(person1 instanceof Person);
这种方法是将say方法拿出来作为全局函数,但是这样导致window也可以进行调用,失去了封装的意义,而且后面代码越写越多之后,方法越来越多,后期开发起来和优化起来都特别麻烦。
因为以上方法都不理想,所以用原型的方法来创建对象

function Person(){}
Person.prototype.name = "xiaobao";
Person.prototype.age = 18;
Person.prototype.sex = "男";
Person.prototype.say = function(){
	console.log(this.name+this.age+this.sex);
}
var person1 = new Person();
person1.say();
console.log(person1 instanceof Person);


//用来检测person1是不是指向Person的原型对象
console.log(Person.prototype.isPrototypeOf(person1));
先定义一个对象(首字母大写),再使用原形来给对象赋值,这样就将对象的属性和值放在了对象原型中,而且say方法只有对象自身可以访问,外界无法访问。
原型是js中非常特殊一个对象,当一个函数创建之后,会随之就产生一个原型对象,当通过这个函数的构造函数创建了一个具体的对象之后,在这个具体的对象中就会有一个属性指向原型。

//用来检测person1是不是指向Person的原型对象
console.log(Person.prototype.isPrototypeOf(person1));
//检测person1的构造器是不是指向Person对象
console.log(p1.constructor == Person);
//检测属性是不是在自己的内存中
console.log(p1.hasOwnProperty("name"));
			
			
//可以用delete语句来删除我们赋予对象自己的属性,但是原型中的是无法删除的
delete p1.name;
			
			
//检测某个对象自己或者对应的原型中是否存在某个属性
console.log("name" in p1);
//检测属性不在自己,在原型中
function hasPrototypeProperty(obj,prop) {
	if (!obj.hasOwnProperty(prop)) {
		if (prop in obj) {
			return true;
		}
	}
	return false;
}
console.log(hasPrototypeProperty(p1,"name"));
原型重写
如果对象中存在大量的属性或者方法的时候,使用之前的方式,感觉要写大量的【对象.prototype.属性名 】,感觉不是很好, 那么json的方式来写:
function Person() {}
Person.prototype = {
	name : "xiaobao",
	age : 18,
	say : function() {
		alert("我的名字是: "+this.name+",我今年"+this.age+"岁了");
	}
}
var p1 = new Person();
p1.say()
var p2 = new Person();
p2.name = "张三";
p2.age = 20;
p2.say();
但是这种写法,是将该对象的原型覆盖(这两种写法不一样的, 第一种是扩充,第二种是覆盖) 
function Person() {}
Person.prototype = {
	constructor:Person,//手动指向Person
	name : "刘帅哥",
	age : 18,
	say : function() {
		alert("我的名字是: "+this.name+",我今年"+this.age+"岁了");
	}
}
var p1 = new Person();
p1.say()
var p2 = new Person();
p2.name = "张三";
p2.age = 20;
p2.say();
//此时p1的构造器不在指向Person,而是指向了Object
//因为我们覆盖了Person的原型,所以如果constructor比较重要的话,</span><span style="color:#f8f8f2;font-weight: normal; font-family: Consolas; font-size: 10pt;">
//我们可以收到指向
console.log(p1.constructor == Person);
封装--原型创建对象
因为原型存在,我们实现了对象的封装,但是这种封装也同样可能存在问题的。
1、 我们无法像使用构造函数的那样将属性传递用于设置值
2、 当属性中有引用类型, 可能存在变量值的重复

function Person() {}
Person.prototype = {
	constructor:Person,
	name : "刘帅哥",
	age : 18,
	friends:["老孙","老牟"],
	say : function() {
		alert("我的名字是: "+this.name+",我今年"+this.age+"岁了");
	}
};
var p1 = new Person();
p1.friends.push("老刘");
alert(p1.friends);
//因为p1和p2对象指向了同一个原型链,所以当p1的friends发生变化是p2页就跟着
var p2 = new Person();
alert(p2.friends);
为了解决原型所带来的问题,需要通过组合构造函数和原型来实现对象的创建将:属性在构造函数中定义,将方法在原型中定义。这种有效集合了两者的优点,是目前最为常用的一种方式。
//属性在构造方法定义
function Person(name,age,friends) {
	this.name = name;
	this.age = age;
	this.friends = friends;
}
/**
* 此时所有的属性都是保存在自己的内存中
* 方法都是定义在prototype(原型)中
*/
//方法在原型中定义
Person.prototype = {
	constructor:Person,
	say : function() {
	alert("我的名字是: "+this.name+",我今年"+this.age+"岁了");
	}
};
var p1 = new Person("刘帅哥",18,["老孙","老徐"]);
p1.friends.push("老刘");
alert(p1.friends);
var p2 = new Person("曾小贤",20,["小丽","小美"]);
alert(p2.friends);
最终的定义 javascript 对象的方案就是基于组合的方式定义,将属性的定义放在构造函数中,将方法的定义放在原型中。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值