- Published on
javascript中创建对象的几种方式
- Authors
- Name
- 林晓东
- @xiaodong5959
javascript中创建对象有几种方式,工厂模式,构造函数模式,原型模式,构造函数+原型混合模式,动态原型模式,寄生构造函数模式,稳妥构造函数模式.
针对前几种,记录一下自己的书写笔记,有时间再来整理一下文字版.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>对象</title>
<script>
//工厂方法 缺点:对象识别问题.
function CreatPerson(name,age){
var obj = new Object;
obj.name = name;
obj.age = age;
obj.fav = ["苹果","葡萄"];
obj.run = function (){
return this.name+this.age+"正在运行中...";
};
return obj;
}
/*
var person1 = CreatPerson("lxd",23);
person1.fav.push("橙子");
var person2 = CreatPerson("tian",14);
person1.name = "xiaodong";
console.log(person1.run());//xiaodong23正在运行中...
console.log(person1.fav);// ["苹果", "葡萄", "橙子"] 引用对象不共享
console.log(person2.run());//tian14正在运行中...
console.log(person2.fav);// ["苹果", "葡萄"]
console.log(person1 instanceof Object);//true
console.log(person1 instanceof CreatPerson);//false 不能获得对象标识
console.log(person1.run == person2.run);//false
*/
//构造函数模式 缺点:里面相同任务的function也会被实例化
function Person(name,age){
this.name = name;
this.age = age;
this.fav = ["苹果","葡萄"];
this.run = function(){ //这里的方法也会被实例化,等同于this.run = new Function("return this.name+this.age+'正在运行中...';")
return this.name+this.age+"正在运行中...";
}
}
var person1 = new Person("lxd",23);
person1.fav.push("橙子");
var person2 = new Person("tian",14);
person1.name = "xiaodong";
console.log(person1.run());//xiaodong23正在运行中...
console.log(person1.fav);// ["苹果", "葡萄", "橙子"] 引用对象不共享
console.log(person2.run());//tian14正在运行中...
console.log(person2.fav);// ["苹果", "葡萄"]
console.log(person1 instanceof Object);//true
console.log(person1 instanceof Person);//true 可以获得对象标识
console.log(person1.run == person2.run);//false 实例化对象,里面的方法也会实例化
Person("window",100);//当作普通函数使用 添加到window对象中
console.log(window.run());//window100正在运行中...
var o = new Object;
Person.call(o,"oooo",99);//在另外一个对象的作用域中调用
console.log(o.run());//oooo99正在运行中...
//针对构造函数的缺点,进行改造,把函数提取出来 缺点:暴躁在全局变量中的方法,却只能在对象中使用,而且如果方法很多,会创建很多这样的全局方法.
function NewPerson(name,age){
this.name = name;
this.age = age;
this.fav = ["苹果","葡萄"];
this.run = run;
}
function run(){
return this.name+this.age+"正在运行中...";
}
var newperson1 = new NewPerson("xiaodong",13);
var newperson2 = new NewPerson("tian",22);
console.log(newperson1.run == newperson2.run);//true 访问的是同一个方法
</script>
</head>
<body>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>prototype</title>
<script>
//原型模式
function Person() {};
Person.prototype.name = "xiaodong";
Person.prototype.age = 23;
Person.prototype.job = "do software";
Person.prototype.sayName = function (){
return this.name;
}
var person1 = new Person();
var person2 = new Person();
console.log(person1.sayName());//"xiaodong"
console.log(person2.sayName());//"xiaodong"
console.log(person1.sayName === person2.sayName);//访问同一个对象指针
console.log(Person.prototype.isPrototypeOf(person1));//true person1中包含有指向Person.prototype的指针
console.log(Object.getPrototypeOf(person1) == Person.prototype);//true page 149 返回prototype的值
console.log(Object.getPrototypeOf(person1).name);//xiaodong
person1.name = "tiantian"; //只能添加到实例中,不能改变原型的值
console.log(person1.name);//"tiantian" 来自实例而非原型
console.log(person2.name);//"xiaodong" 来自原型而非实例
delete person1.name;
console.log(person1.name);//"xiaodong" 来自原型
/*
console.log(person1.hasOwnProperty("name"));//false 检测是实例属性还是原型属性
person1.name = "tian";
console.log(person1.hasOwnProperty("name"));//ture 实例中包含name属性
*/
console.log("name" in person1);//true 可枚举原型中的属性 来自原型
person1.name = "okok";
console.log("name" in person1);//true //来自实例
//利用hasOwnProperty和in可以判断属性是来自实例还是原型例如
function hasPrototypeProperty(object,name){
return !object.hasOwnProperty(name) && (name in object);
}
delete person1.name;
console.log(hasPrototypeProperty(person1,"name"));//ture
person1.name = "test";
console.log(hasPrototypeProperty(person1,"name"));//false
for (var i in person1){
if (i == "age"){
console.log("1234");//"1234"
}
}
var keys = Object.keys(Person.prototype);
console.log(keys);//["name", "age", "job", "sayName"]
var keys = Object.keys(person1);
console.log(keys);// ["name"] 实例属性
Person.prototype.toString = function(){
return "ok";
}
var keys = Object.getOwnPropertyNames(Person.prototype);
console.log(keys);// ["constructor", "name", "age", "job", "sayName", "toString"] 包含不可枚举的 注意还有tostring;
var keys = Object.getOwnPropertyNames(person1);
console.log(keys);// ["name"] 证明只有构造函数才有constructor等方法
//person1.prototype.name = "dfsa"; //TypeError: person1.prototype is undefined
function NewPerson(){};
NewPerson.prototype = {//采用字面量的方式书写;
name:"xiaodong",
age: 23,
sayName: function(){
return this.name;
}
};
var newperson = new NewPerson();
console.log(newperson instanceof Object);//ture
console.log(newperson instanceof NewPerson);//ture
console.log(newperson.constructor == NewPerson);//false 重写了默认的prototype,所以其constructor属性变成了新对象的constructor属性(指向Object);
console.log(newperson.constructor == Object);//ture
function NewPerson2(){};
NewPerson2.prototype = {//采用字面量的方式书写;
constructor:NewPerson2,//显式指定
name:"xiaodong",
age: 23,
sayName: function(){
return this.name;
}
};
var newperson2 = new NewPerson2();
console.log(newperson2.constructor == NewPerson2);//ture;
NewPerson2.prototype.name = "tiantian";
console.log(newperson2.name);//原型的动态性 对其修改会在所有的对象实例中反映出来
NewPerson2.prototype = {//但如果重写的话,就会切断构造函数与最初原型的关系 page156 实例中的指针仅指向原型,而不是构造函数
name : "other"
};
console.log(newperson2.name);//tiantian
console.log(newperson2.constructor === NewPerson2)//true
//原型模式的缺点:所有的属性都是共享的.
function Friend(){};
Friend.prototype={
name:"jack",
fav:["苹果","葡萄"],
run:function(){
return this.fav;
}
};
var friend1 = new Friend();
var friend2 = new Friend();
friend1.fav.push("梨子");//引用类型
console.log(friend1.fav);// ["苹果", "葡萄", "梨子"] 引用类型
console.log(friend2.fav);// ["苹果", "葡萄", "梨子"] 引用类型
//组合使用构造函数模式和原型模式 目前最常用的方式
function Base(name,age){
this.name = name;
this.age = age;
};
Base.prototype.run = function(){
return this.name;
};
var base1 = new Base("xiaodong",23);
var base2 = new Base("tiantian",22);
console.log(base1.run());//"xiaodong"
console.log(base2.run());//"tiantian"
console.log(base1.run === base2.run);//true
</script>
</head>
<body>
</body>
</html>