js-对象

1. 对象的创建

// 创建person对象
let person = new Object();
person.name = "张三";
person.age = 18;
person.sayName = function(){
    console.log(this.name);
}

// 对象字面量
let person = {
    name:"张三",
    age:18,
    sayName(){
        console.log(this.name);
    }
};

// 可以使用Object.defineProperty()来修改对象默认属性
Object.defineProperty(person, "name", {
    Writable: false, // 数据属性,表示属性的值不可被修改
    value: "mike"
})
console.log(person.name) //mike
person.name = "jack";
console.log(person.name) //mike

//访问器属性 getter\setter
let book = {
    year_:2017,    //_常用来表示私有属性
    edition:1
};
Object.defineProperty(book, "year", {
   get(){
        return this.year_;
    },
    set(newValue){
        if(newValue > 2017) {
            this.year_ = newValue;
            this.edition += newValue - 2017;
        }
    }
});
book.year = 2018;
console.log(book.edition); //2

//同时定义多个属性
let book = {};
Object.defineProperties(book, {
    year_:{
        value: 2017
    },
    edition: {
        value: 1
    },
    year: {
        get(){
            return this.year_;
        },
        set(newValue){
            if(newValue > 2017) {
                this.year_ = newValue;
                this.edition += newValue - 2017;
            }
        }
    }
});

1.1 工厂模式

function createPerson(name, age, job){
    let o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName(){
        console.log(this.name);
    };
    return o;
}

let person = createPerson("Greg", 23, "Student");

1.2 构造函数模式

任何函数只要使用了new操作符调用就是构造函数。

//区别
// 1.没有显示的创建对象
// 2.属性和方法直接赋值给this
// 3.没有return
funciton Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName(){
        console.log(this.name);
    };
}

let person1 = new Person("Tom", 18, "Student");
let person2 = new Person("Jack", 18, "Student");
console.log(person1.constructor == Person); // true
console.log(person1.sayName === person2.sayName); // false 不同实例上的函数虽然同名但不相等

面试题:new操作符做了些什么

  1. 在内存中创建了一个对象;
  2. 在这个新对象的内部的Prototype特性被赋值为构造函数的prototype属性;
  3. 构造函数内部的this指向新对象;
  4. 执行构造函数内部的代码(给新对象添加属性);
  5. 如果构造函数返回非空对象,则返回该对象;否则返回刚创建的新对象。

1.3 原型模式

原型

函数即为对象,对象则有属性,在JS中将函数的prototype属性称为原型,也称显式原型,prototype指向的对象就是原型对象,所有原型对象自动获取constructor属性,指回与之关联的构造函数。每个对象会有隐式原型__proto__属性,通过这个属性可以访问对象的原型。

每个函数都会创建一个prototype属性,这个属性是一个对象,包含应该由特点引用类型的实例共享的属性和方法。

function Person() {};
Person.prototype.name = "Jerry";
Person.prototype.age = 29;
Person.prototype.job = "SE";
Person.prototype.sayName = function() {
    console.log(this.name);
};

let person1 = new Person();
person1.sayName(); // "Jerry"

let person2 = new Person();
person2.sayName(); // "Jerry"

console.log(person1.sayName == person2.sayName); // true

console.log(Person.prototype.constructor === Person); // true

// 构造函数Person、原型对象Person.prototype、实例person1是三种完全不同的对象
console.log(person1.__proto__ === Person.prototype); // true
console.log(person1.__proto__ === person2.__proto__); // true
console.log(Person.prototype.isPrototypeOf(person1)); // true
console.log(Object.getPrototypeOf(person1) == Person.prototype); // true

2. 继承

1. 原型链

 原型本身有一个内部指针指向另一个原型,相应的另一个原型也有一个指针指向另一个构造函数,这样实例与原型之间构造了一条原型链。

function SuperType(){
    this.property = true;
}

SuperType.prototype.getSuperValue = function() {
    return this.property;
}

function SubType() {
    this.subproperty = false;
}

// 继承
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function () {
    return this.subproperty;
}

let instance = new SubType();
console.log(instance.getSuperValue()); // true

 问题:

  1.  原型中包含的引用值会在所有实例间共享,容易造成修改混乱;
  2.  子类型在实例化时不能给父类型的构造函数传参。

解决方法:

  • 盗用构造函数:通过call()或者apply()方法在子类构造函数中调用父类构造函数

        缺点:必须在构造函数中定义方法,因此函数不能重用;子类也不能够访问父类原型上定义的方法。

function SuperType(){
    this.colors = ["red","green","blue"];
}

function SubType(){
    SuperType.call(this);
}

let instance1 = new SubType();
instance1.colors.push("black");
console.log(instance1.colors); //"red,green,blue,black"

let instance2 = new SubType();
console.log(instance2.colors); //"red,green,blue"

 2.  组合继承

使用原型链继承原型上的属性和方法,通过盗用构造函数继承实例属性。

缺点:父类构造函数始终会被调用两次

function SuperType(name){
    this.name = name;
    this.colors = ["red","green","blue"];
}

SuperType.prototype.sayName = function() {
    console.log(this.name);
}

function SubType(name, age){
    // 继承属性
    SuperType.call(this, name);
    this.age = age;
}

// 继承方法
SubType.prototype = new SuperType();

SubType.prototype.sayAge = function() {
    console.log(this.age);
}

let instance1 = new SubType("Tom",29);
instance1.colors.push("black");
console.log(instance1.colors); //"red,green,blue,black"
instance1.sayName(); //"Tom"
instance1.sayAge(); //29

let instance2 = new SubType("Greg",27);
console.log(instance2.colors); //"red,green,blue"
instance2.sayName(); //"Greg"
instance2.sayAge(); //27

3. 原型式继承

不自定义类型也可以通过原型实现对象之间的信息共享。

let person = {
    name: "Tom",
    friends: ["Shelby", "Van"]
}

let person1 = Object.create(person);
person1.name = "Greg";
person1.friends.push("Bob");

let person2 = Object.create(person);
person2.name = "Linda";
person2.friends.push("Josh");

console.log(person.friends); // "Shelby,Van,Bob,Josh"

 4. 寄生式组合继承

通过盗用构造函数继承属性,使用混合式原型链集成方法,不通过调用父类构造函数给子类原型赋值,是引用类型继承的最佳模式。

function inheritPrototype(subType, superType){
    let prototype = object(superType.prototype); // 创建对象
    prototype.constructor = subType;    // 增强对象
    subType.prototype = prototype;    // 赋值对象
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值