字面量创建对象
<script>
var age = 111;
let obj = {
name:"wangcai",
age:100,
// 此时这个this表示window
weight:this.age+10 // this表示什么 NaN
}
// 在一个对象的方法中,如果有this,通过这个对象调用方法时
// 方法中的this是对象
console.log(obj.weight)
</script>
工厂模式
function createRect(w,h) { // 工厂函数
var obj = {};
obj.width = w;
obj.height = h;
obj.getS = function () {
return this.width * this.height
}
return obj;
}
var rect1 = createRect(1,2);
console.log(rect1.getS());
var rect2 = createRect(2,2);
console.log(rect2.getS());
优点:可以批量创建对象 解决了创建多个对象代码复用问题
缺点:使用工厂模式创建的对象,没有解决对象识别的问题(就是怎样知道一个对象的类型是什么)
构造函数模式
function createPerson(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.sayName = function(){
alert(this.name);
};
return o;
}
var person1 = new createPerson("james",9,"student");
var person2 = new createPerson("kobe",9,"student");
当我们使用构造函数实例化一个对象的时候,对象中会包含一个 proto 属性指向构造函数原型对象,而原型对象中则包含一个 constructor 属性指向构造函数。因此在实例对象中我们可以通过原型链来访问到 constructor 属性,从而判断对象的类型。
优点:解决了工厂模式中对象类型无法识别的问题,并且创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型。
缺点:我们知道 ECMAScript 中的函数是对象,在使用构造函数创建对象时,每个方法都会在实例对象中重新创建一遍。拿上面的例子举例,这意味着每创建一个对象,我们就会创建一个 sayName 函数的实例,但它们其实做的都是同样的工作,因此这样便会造成内存的浪费。
原型
function Person(){
}
Person.prototype.name = "james";
Person.prototype.age = 9;
Person.prototype.job = "student";
Person.prototype.sayName = function(){
alert(this.name);
}
var person1 = new Person();
person1.sayName(); // "james"
var person2 = new Person();
person2.sayName(); // "james"
console.log(person1.sayName === person2.sayName) // true
与构造函数模式不同的是,原型对象上的属性和方法是有所有实例所共享的。也就是说,上面 person1 和 person2 访问的都是同一组属性和同一个 sayName() 函数。
优点:解决了构造函数模式中多次创建相同函数对象的问题,所有的实例可以共享同一组属性和函数。
缺点:
首先第一个问题是原型模式省略了构造函数模式传递初始化参数的过程,所有的实例在默认情况下都会取得默认的属性值,会在一定程度上造成不方便。
因为所有的实例都是共享一组属性,对于包含基本值的属性来说没有问题,但是对于包含引用类型的值来说(例如数组对象),所有的实例都是对同一个引用类型进行操作,那么属性的操作就不是独立的,最后导致读写的混乱。我们创建的实例一般都是要有属于自己的全部属性的,因此单独使用原型模式的情况是很少存在的。
通过构造器+原型来创建JS中的对象
function Rect(w,h) {
this.w = w; // 私有属性
this.h = h; // 私有属性
}
Rect.prototype.getS = function () { // 将方法当成一个公共属性
return this.w*this.h;
}
// rect1 rect1是通过Rect构造器构造的
var rect1 = new Rect(1,2);
console.log(rect1.getS());
var rect2 = new Rect(3,2);
console.log(rect2.getS());
优点:采用了构造函数模式和原型模式的优点,这种混成模式是目前使用最广泛,认同度最高的一种创建自定类型的方法。
缺点:由于使用了两种模式,因此对于代码的封装性来说不是很好。
ES6中通过class创建对象
<script>
// react
class NBAPlayer{
constructor(name,age) {
this.name = name;
this.age = age;
}
score = 100; // 私有属性
run(){ // 公有方法
console.log("run....")
}
static xx = "123"; // 类上的属性 静态属性
}
var nbaPlayer1 = new NBAPlayer("qd",40);
console.log(nbaPlayer1.name)
console.log(nbaPlayer1.age)
console.log(nbaPlayer1.score)
console.log(nbaPlayer1.run())
console.log(NBAPlayer.xx)
</script>