1.new Object()
缺点:步骤多
2.字面量{}
var obj = {}
缺点:如果反复创建多个对象,代码冗余
3.工厂函数方式
反复生产,一个一个一个,叫工厂模式
function createPerson(name, age) {
var o = new Object();
o.name = name;
o.age = age;
o.say = function() {
return o;
}
}
var lilei = createPerson("lilei", 12);
缺点:将来没有办法判断类型,因为返回的对象,都是new Object
4.构造函数
function Person(name, age) {
this.name = name;
this.age = age;
this.intr = function() {} // 这个方法的缺点是浪费内存
}
var lilei = new Person("lilei", 12);
构造函数有一个特点:
构造函数内部,如果return一个引用类型的对象,则整个构造函数失效。而是返回这个引用类型的对象而已- 如果返回的是this,new构造的时候,返回的是新对象。如果只是执行函数,要看作用域,正常可能是window
- 如果返回的是普通数据类型(string、number等)则正常构造
5.原型对象方式
所有属性和方法都通过原型对象(prototype)来实现。
但是js中要求:禁止修改共有属性。而是处理自己的自由属性
function Person() {} // 构造函数,什么都不干,因为我要把所有的属性和方法都放到原型对象上面
Person.prototype.name = "主人太懒";
Person.prototype.age = 0;
Person.prototype.intr = function() { console.info(this.name); }
var p1 = new Person();
p1.name = "lilei"; // 不能改原型,但是可以给自己添加自由属性(这里是name),可以看下图
var p2 = new Person();
p2.name = "han meimei"
console.info(p1);
console.info(p2);
缺点:太繁琐了
6.混合模式(推荐)
也就是方法4和方法5的结合
// 构造函数
function Person(name, age) {
this.name = name;
this.age = age;
}
// 原型对象
Person.prototype.intr = function() {
console.info(this.name);
}
var lilei = new Person("lilei", 12);
缺点:不符合封装。因为构造函数和给函数原型对象添加方法,是分开做的
7.动态混合模式
先创建完全相同的对象,再给子对象添加个性化属性
function Person(name,age){
this.name = name;
this.age = age;
if (Person.prototype.intr === undefined) {
Person.prototype.intr = function() {
console.info(this.name)
}
}
}
var p1 = new Person("lilei", 12);
var p2 = new Person("hanmeimei", 12);
缺点:语义不符,只在if创建第一次对象时有意义
8.寄生构造函数
function Person(name,age){
this.name = name;
this.age = age;
if (Person.prototype.intr === undefined) {
Person.prototype.intr = function() {
console.info(this.name)
}
}
}
// 开始了
function Student(name, age, className) {
var p = new Person(name, age);
p.className = className;
return p
}
var p1 = new Student("lilei", 12, "二(8)");
var p2 = Student("hanmeimei", 15, "2") // 也可以不用new,因为Student中没有this
9.class
- 如何定义class?
基于
混合模式(方法6)基础上实现
function Person(name, age) {
this.name = name;
this.age = age;
}
// 原型对象
Person.prototype.intr = function() {
console.info(this.name);
}
然后3步实现class
- 1.用class{}包裹原构造函数 + 原型对象方法
class {
function Person(name, age) {
this.name = name;
this.age = age;
}
// 原型对象
Person.prototype.intr = function() {
console.info(this.name);
}
}
- 2.把构造函数名提升为class的名字,所有构造函数统一更名为constructor
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
// 原型对象
Person.prototype.intr = function() {
console.info(this.name);
}
}
- 3.所有的原型方法(prototype),不再使用prototype前缀,也不用=function,直接简写为:方法名(){}
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
intr() {
console.info(this.name);
}
}
只是新瓶装旧酒,换汤不换药
10.稳妥构造函数
利用闭包,不用this,不用new。安全,可靠
function Person(name, age) {
var p = new Object();
p.setName = function(value) { name = value }
p.getName = function() { return name }
p.getAge = function() { return name }
return p;
}
var lilei = new Person("lilei", 12);
lilei.getName();
好处:只能通过我提供的api修改值