对象的创建模式
① Object构造函数模式
var obj = {};obj.name = 'Tom'obj.setName = function(name){this.name=name}
* 套路: 先创建空Object对象, 再动态添加属性/方法* 适用场景: 起始时不确定对象内部数据* 问题: 语句太多
② 对象字面量模式
var obj = { name : 'Tom', setName : function(name){this.name = name}}
* 套路: 使用{}创建对象, 同时指定属性/方法* 适用场景: 起始时对象内部数据是确定的* 问题: 如果创建多个对象, 有重复代码
③ 工厂模式
function createPerson(name, age) { //返回一个对象的函数===>工厂函数 var obj = { name: name, age: age, setName: function (name) { this.name = name } } return obj}// 创建2个人var p1 = createPerson('Tom', 12) //Object类型var p2 = createPerson('Bob', 13)
* 套路: 通过工厂函数动态创建对象并返回* 适用场景: 需要创建多个对象* 问题: 对象没有一个具体的类型, 都是Object类型
④ 构造函数模式✅
function Person(name, age) { this.name = name this.age = age this.setName = function (name) { this.name = name }}var p1 = new Person('Tom', 12) //Person类型
* 套路: 自定义构造函数, 通过new创建对象* 适用场景: 需要创建多个类型确定的对象* 问题: 每个对象都有相同的数据, 浪费内存
⑤ 构造函数+原型的组合模式
function Person(name, age) { //在构造函数中只初始化一般函数 this.name = name this.age = age}Person.prototype.setName = function (name) { this.name = name}var p1 = new Person('Tom', 23)var p2 = new Person('Jack', 24)
* 套路: 自定义构造函数, 属性在函数中初始化, 方法添加到原型上* 适用场景: 需要创建多个类型确定的对象
继承模式
① 原型链继承 : 得到方法
<!--方式1: 原型链继承 1. 套路 1. 定义父类型构造函数 2. 给父类型的原型添加方法 3. 定义子类型的构造函数 4. 创建父类型的对象赋值给子类型的原型 5. 将子类型原型的构造属性设置为子类型 6. 给子类型原型添加方法 7. 创建子类型的对象: 可以调用父类型的方法 2. 关键 1. 子类型的原型为父类型的一个实例对象--><script type="text/javascript"> //父类型 function Supper() { this.supProp = 'Supper property' } Supper.prototype.showSupperProp = function () { console.log(this.supProp) } //子类型 function Sub() { this.subProp = 'Sub property' } // 子类型的原型为父类型的一个实例对象 Sub.prototype = new Supper() // 让子类型的原型的constructor指向子类型 Sub.prototype.constructor = Sub Sub.prototype.showSubProp = function () { console.log(this.subProp) } var sub = new Sub() sub.showSupperProp() // sub.toString() sub.showSubProp() console.log(sub) // Sub</script>
② 借用构造函数 : 得到属性
<!--方式2: 借用构造函数继承(假的)1. 套路: 1. 定义父类型构造函数 2. 定义子类型构造函数 3. 在子类型构造函数中调用父类型构造2. 关键: 1. 在子类型构造函数中通用call()调用父类型构造函数--><script type="text/javascript"> function Person(name, age) { this.name = name this.age = age } function Student(name, age, price) { Person.call(this, name, age) // 相当于: this.Person(name, age) /*this.name = name this.age = age*/ this.price = price } let s = new Student('Tom', 20, 14000) console.log(s); console.log(s.name, s.age, s.price)</script>
③ 组合
<!--方式3: 原型链+借用构造函数的组合继承1. 利用原型链实现对父类型对象的方法继承2. 利用super()借用父类型构建函数初始化相同属性--><script type="text/javascript"> function Person(name, age) { this.name = name this.age = age } Person.prototype.setName = function (name) { this.name = name } function Student(name, age, price) { Person.call(this, name, age) // 为了得到属性 this.price = price } Student.prototype = new Person() // 为了能看到父类型的方法 Student.prototype.constructor = Student //修正constructor属性 Student.prototype.setPrice = function (price) { this.price = price } let s = new Student('Tom', 24, 15000) s.setName('Bob') s.setPrice(16000) console.log(s.name, s.age, s.price)</script>
new一个对象背后做了些什么?
- 创建一个空对象
- 给对象设置proto, 值为构造函数对象的prototype属性值 this.proto = Fn.prototype
- 执行构造函数体(给对象添加属性/方法)