js创建对象方法 6种
1.对象字面量
var person = {
name : "xyt", age : 21
};
2.Object构造函数
new Object()
var person = new Object();
person.name = "xyt";
person.age = 21;
3.工厂模式
function newPerson (name, age, gender) {
var p = new Object();
p.name = name;
p.age = age;
p.gender = gender;
p.sayName = function () {
console.log(this.name);
}
return p;
}
var p1 = newPerson('zhangsan', 12, '男');
var p2 = newPerson('lisi', 15, '女');
console.log(p1);
console.log(p2);
p1.sayName();
p2.sayName();
4.构造函数模式
function Person (name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
this.sayName = function () {
console.log(this.name);
}
}
var p1 = new Person('terry', 23, '男');
p1.sayName();
console.log(p1);
console.log(typeof p1);
5.原型模式
function Person () { };
Person.prototype.name = "zhangsan";
Person.prototype.age = 12;
Person.prototype.gender = "男";
Person.prototype.likes = ['吃饭', '读书', '睡觉'];
Person.prototype.sayName = function () {
console.log(this.name);
}
var p1 = new Person();
p1.name = "lisi";
p1.likes.push('niuba');
var p2 = new Person();
p2.name = "wangwu";
p1.sayName();
console.log(p1.likes);
p2.sayName();
console.log(p2.likes);
6.构造原型组合模式
function Person (name, age, gender) {
this.name = name,
this.age = age,
this.gender = gender,
this.likes = []
}
Person.prototype = {
constructor: Person,
sayName: function () {
console.log(this.name);
}
}
var p1 = new Person('larry', 12, '男');
p1.likes.push('篮球');
var p2 = new Person('terry', 23, '男');
p2.likes.push('足球');
console.log(p1);
console.log(p2);
/*实例属性封装在构造函数中;
实例方法定义在原型对象上;*/
js继承的方法 6种
1.原型链继承
核心:让新实例的原型指向父类的实例
// 定义父类类型
function Animal () {
this.name = "animal";
}
Animal.prototype.sayName = function () {
console.log(this.name);
}
// 定义子类
function Dog () {
this.color = "black";
}
// 将子构造函数的原型 指向父类对象的实例
Dog.prototype = new Animal();
Dog.prototype.sayColor = function () {
console.log(this.color);
}
var dog = new Dog();
console.log(dog);
dog.sayName();
dog.sayColor();
优点:实例可继承的属性
实例的构造函数的属性,父类构造函数属性,父类原型的属性
(新实例不会继承父类实例的属性)
缺点:1. 新实例无法向父类构造函数传参
2. 继承单一
3. 所有新实例都会共享父类实例的属性
(原型上的属性是共享的,一个实例修改原型属性,其他实例原型属性也会被修改)
2.借用构造函数(又叫经典继承)
核心:用.call()和.apply()将父类构造函数引入子类函数(在子类函数中做了父类函数的自执行(复制))
function Animal (name, age) {
this.name = name;
this.age = age;
this.sayName = function () {
console.log(this.name);
}
}
Animal.prototype.sayAge = function () {
console.log(this.age);
}
function Dog (name, age, color, type) {
// this.name = name;
// this.age = age;
// 借用构造函数
// 找到父类
Animal.call(this, name, age);
this.color = color;
this.type = type;
}
var dog = new Dog('铃铛', 1, 'yellow', '金毛');
console.log(dog);
dog.sayName();
// dog.sayAge(); //报错 因为是父类原型中的方法
优点:1.只继承了父类构造函数的属性,没有继承父类原型的属性
2.解决了原型链继承的1、2、3缺点
3.可以继承多个构造函数属性(call多个)
4.在子类实例中可向父类实例传参
缺点:1.只能继承父类构造函数的属性
2.无法实现构造函数的复用(每次用都要重新调用)
3.每个新实例都有父类构造函数的副本,造成代码冗余
3.组合继承(原型链继承+借用构造函数继承)
核心:可以传参和复用
function Animal (name, age) {
this.name = name;
this.age = age;
this.sayAge = function () {
console.log(this.age);
}
}
Animal.prototype = {
constructor: Animal,
sayName: function () {
console.log("hello,my name is" + this.name);
}
}
function Dog (name, age, type) {
// 经典继承
Animal.call(this, name, age);
this.type = type;
}
// 原型链继承
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
Dog.prototype.sayType = function () {
console.log(this.type);
}
var dog = new Dog("金毛", "萨摩耶", "哈士奇");
console.log(dog);
dog.sayName();
dog.sayType();
dog.sayAge();
优点:1.可以继承父类原型上的属性,可以传参,可以复用
2.每个新实例引入的构造函数属性是私有的
缺点:调用两次父类构造函数(消耗内存),子类的构造函数会代替原型上的父类构造函数
4.原型继承
核心:用一个函数包装一个对象,然后返回这个函数的调用,这个函数变成了可以随意增加属性的实例或对象。object.create()就是这个原理
优点:类似于复制一个对象,用函数来包装
缺点:1.所有实例都会继承原型上的属性
2.无法实现复用
(新实例属性都是后面添加来的)
5.寄生式继承
核心:原型式继承外面套壳子
优点:没有创建自定义类型,因为只是套个壳子返回这个对象,这个函数就成了创建的新对象
缺点:没用到原型,无法复用
6.寄生组合式继承
核心:修复组合继承问题