首先,在js里,对象是由函数构建而成的。
创建对象的几种模式
1.工厂模式
function person(name,age,job) {
var o=new Object();
o.age=age;
o.name=name;
o.job=job;
o.sayname=function () {
console.log(this.name);
}
return o;
}
var person1=person("1",1,"1");
person1.sayname();
//检测对象什么类型
console.log(person1 instanceof Object);//true
console.log(person1 instanceof person);//FALSE
工厂模式解决了创建多个相似对象的问题,但是不知道如何知道一个对象的类型。
2.构造函数模式
function person(name,age,job) {
this.name=name;
this.age=age;
this.job=job;
this.sayname=function () {
console.log(this.name);
}
}
var person1=new person("1",1,"1");
person1.sayname();
console.log(person1 instanceof Object);//检测对象什么类型
console.log(person1 instanceof person);//都是true
与工厂模式不同点:
1.没有显式创建对象
2.属性方法赋予给this对象
3.没有return语句
创建对象使用new时,调用构造函数会有一下几步
1.创建一个新对象
2.构造函数的作用域给新对象
3.执行构造函数的代码
3.返回新对象
任何函数,只要通过new来调用,那么他就可以作为构造函数,他的问题就是每个方法要在每个实例上重新构造一遍
上述sayname方法等同于下
this.sayname=new function("console.log(this.name)")
如果再新建对象person2
console.log(person1.sayname==person2.sayname) ;结果是FALSE
当然我们可以把这些函数放在外面,在构造函数内调用,但是这样就毫无封装性。3.
3.原型模式
每个函数都有一个prototype属性
function person() {
}
person.prototype.name="1";
person.prototype.age=12;
person.prototype.sayname=function () {
console.log(this.name);
}
var person1=new person();
person1.sayname(); //1
var person2=new person();
person2.sayname(); //1
好处:让所有实例共享他的属性和方法
如果实例添加一个新属性且新属性与原型中的属性重名,那么就在实例中创建该属性,该属性会屏蔽掉原型中的该属性。
function person() {
}
person.prototype.name="1";
person.prototype.age=12;
person.prototype.sayname=function () {
console.log(this.name);
}
var person1=new person();
person1.name="2";
person1.sayname();
delete person1.name;//删除新添加的属性
person1.sayname(); //会显示原型里的属性
接下来是重点:
function person() {
}
person.prototype={
name:"1",
age:12,
sayname:function () {
console.log(this.name);
}
}
var friend=new person();
console.log(friend instanceof Object); //true
console.log(friend instanceof person); //true
console.log(friend.constructor == person); //false
console.log(friend.constructor == Object);//true
person.prototype.sayhi=function () {
console.log("hi");
}
friend.sayhi(); //hi
instanceof 判断一个变量是不是属于一个变量的实例。
constructor 属性返回对创建此对象的数组函数的引用。
friend是person的一个实例
所以向person中添加 Protype时friend也可以引用。
原型的动态性:
function person() {
}
var friend=new person();
console.log(friend instanceof Object); //true
console.log(friend instanceof person); //true
console.log(friend.constructor == person); //true
console.log(friend.constructor == Object); //true
console.log(friend.constructor); //【Function:person】
person.prototype={
constructor:person,
name:"1",
age:12,
sayname:function () {
console.log(this.name);
}
}
friend.sayname();//报错
当执行到最后一句时会报错,原因是我们重写了整个原型对象。
大致就是这个样子,person原本指向person Protype,在重写原型对象后指向了new person Protype,但是friend仍然指向原来的person Protype,所以出现错误。
原型模式的问题:
function person() {
}
person.prototype={
constructor:person,
friends:["a","b","c"]
}
var person1=new person();
var person2=new person();
person1.friends.push("d");
console.log(person1.friends);//【a,b,c,d】
console.log(person2.friends);//[a,b,c,d]
会发现person2的friends也会有d
针对包含引用类型值的属性:
原因就是这个样子,person1引用Protype,所以修改person1就修改了person2。
最常用的创建对象对象
--------------------组合使用构造函数模式和原型模式
因为构造函数模式new时会创建一个新对象,而原型模式就是用于定义方法和共享属性。
function person(name) {
this.name=name;
this.friends=['a']
}
person.prototype={
constructor:person,
sayname:function () {
console.log(this.name);
}
}
var person1=new person("1") ;
var person2=new person("2") ;
person1.friends.push("b");
console.log(person1.friends);
console.log(person2.friends);
console.log(person1.friends==person2.friends);
console.log(person1.sayname==person2.sayname);
结果:
[ 'a', 'b' ]
[ 'a' ]
false
true
到这相信大家对JS构建对象有了一定的了解了!
转载于:https://www.cnblogs.com/lilight/p/7520255.html
原文链接:https://blog.csdn.net/weixin_30342827/article/details/98621278
本站声明:网站内容来源于网络,如有侵权,请联系我们,我们将及时处理。
还没有人抢沙发呢~