- JS对象一般生成方式:
var person1 = {
name: 'Jack',
age: 18,
sayName: function () {console.log(this.name)},
}
var person2 = {
name: 'Mike',
age: 16,
sayName: function () {console.log(this.name)},
}- 工厂模式解决方案:封装的对象作为函数的返回值
function createPerson (name, age) {
return {
name: name,
age: age,
sayName: function () {console.log(this.name)},
}
}
var person1_return = createPerson('Jack', 18)
console.log(person1_return.name)//Jack
var person2_return = createPerson('Mike', 16)
person2_return.sayName()//Mike把一个对象用函数封装,并作为函数的返回值,就可以用此函数获取对象的属性值。给定不同参数就是不同对象。但没有解决封装的函数的对象特征识别问题。
- 构造函数解决方案:new操作符衍生对象类型属性
constructor
function Person (name, age) {
this.name = name;
this.age = age;
this.sayName = function () {console.log(this.name)};
}
var person1_new = new Person('Jack', 18)
person1_new.sayName()//Jack
var person2_new = new Person('Mike', 16)
console.log(person1_new.name)//Mikenew操作符的原理 当使用 new 操作符调用 Person() 的时候,实际上这里会先创建一个对象var instance = {}, 然后让内部的 this 指向 instance对象,this = instance 接下来所有针对 this 的操作实际上操作的就是 instance, 在函数的结尾处会将this返回,return this,也就是返回instance。
该方案可以识别对象的具体类型了。每一个实例对象中有一个constructor属性,该属性指向创建该实例的构造函数,但该方案存在一个浪费内存的问题,每一个实例对象syaName都是一模一样的内容,每一次生成一个实例,都必须生成重复的内容,多占用一些内存,如果实例对象很多,会造成极大的内存浪费。
- 更好的解决方案:prototype原型继承,属性共享 。
function Person (name, age) {
this.name = name;
this.age = age;
this.sayName = function () {console.log(this.name)};
}
Person.prototype.sayAge = function () {console.log(this.age)}
var p1 = new Person('Jack', 18)
p1.sayName() // => Jack
p1.sayAge() // => 18
var p2 = new Person('Mike', 16)
p2.sayName() // => Mike
p2.sayAge() // => 16
console.log(p1.constructor === Person) // => true
console.log(p1.__proto__ === Person.prototype) // => true
console.log(p1.__proto__.constructor === Person) // => true每一个实例对象都具有一个 constructor 属性指向创建该实例的构造函数,对象的constructor 属性最初用来标识对象类型,现在推荐使用instanceof操作符。
每一个实例对象都具有一个__proto__ 属性,指向创建该实例的构造函数的原型对象,即构造函数的prototype属性。
console.log(p1.sayName === p2.sayName)// => flase
console.log(p1.sayAge === p2.sayAge) // => true 每个构造函数都有一个prototype属性指向该构造函数的原型对象,所有对象实例需要共享的属性和方法定义这个对象上。未定义在prototype属性上的属性new出来的属性指针不同。
- 番外:原型式继承
Object.create()基于已有的对象创建新对象。
function object(o){
function F(){}
F.prototype = o;
return new F();
}
var person = {name:"jack"}
var person1= object(person)
console.log(person1.name);//jackES5通过Object.create()方法规范了原型继承,Object.create()===object()
var person2 = Object.create(person)
console.log(person2.name);//jackES6类class(ES6类的所有方法都定义在ES5构造函数prototype属性上)
class Point {
constructor(x, y) { //默认方法
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
var point = new Point(2, 3);
console.log(point.toString())//(2,3)