Hibop / Hibop.github.io

Hibop 个人博客
https://hibop.github.io/
23 stars 1 forks source link

关于对象创建和对象继承之N中方法 #10

Open Hibop opened 6 years ago

Hibop commented 6 years ago

1. 创建对象:

  1. new Object()

    var person = new Object();
    pserson.name = 'ifyour';
    person.age = 18;
    person.sayName = function() {
    console.log(this.name);
    }
  2. 字面量

    vaer person = {
    name: 'ifyour',
    age: 18,
    sayName: function(){
        console.log(this.name);
    }
    }
  3. 工厂模式

    function createPerson(name, age){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.sayName = function(){
        console.log(this.name);
    }
    return o;
    }
  4. 构造函数模式: new Object是构造函数的特殊

    function Person(name, age){
    this.name = name;
    this.age = age;
    this.sayName = function(){
        console.log(this.name);
    }
    }
    var person = new Person('ifyour', 18);
    person.sayName(); // => ifyour

    注意: 箭头函数无法new 创建

  5. 原型模式

    
    function Person(){
    }

Person.prototype.name = 'ifyour'; Person.prototype.age = 18; Person.prototype.sayName = function(){ console.log(this.name); }

var person1 = new Person(); var person2 = new Person(); person1.sayName(); // => ifyour console.log(person1.sayName == person2.sayName); // => ture


6. Object.create()创建
Object.create与new区别:
- 1.Object.create传入对象将作为新建对象的原型。
- 2.Object.create传入构造函数原型时,无论构造函数是否返回对象,Object.create只会return 以构造函数原型来新建的对象(参见下面的polyfill),而new则会返回return的obj对象。

7. class语法糖,extend, super()等

### 对象继承
1. 原型链继承:重写原型对象,使子类原型对象指向父类的实例(包括私有和共享原型)以实现继承。
```js
function Person(){
    this.age = 20;
}
Person.prototype.getPersonAge = function(){
    console.log( this.age );
}
function Student(){
    this.name = "zhangsan";
}
// 继承 Person
Student.prototype = new Person();
Student.prototype.constructor = Student; // 注意此处注释很重要,Student.prototype上有constructor指向Student构造函数,重写后需要重新挂载,否则构造函数指向Person
let zhangsan = new Student();
zhangsan.getPersonAge();    // 20

缺点: 不能向父类传参; 改变一个子类实例会影响到其他

  1. 构造函数(call继承):解决原型中包含引用类型值所带来问题的过程中,开发人员开始使用一种叫叫做借用构造函数(constructor stealing)的技术(有时候也叫做伪造对象或经典继承)。 这种技术的基本思想相当简单,即在子类构造函数内部调用父类构造函数,但是需要结合apply()和call()方法改变this指向同时执行。
function Person(name, age){
    this.name = name;
    this.age = age;
    this.sayName = function(){
        console.log( this.name );
    }
}
// call继承只会继承父类的实例私有属性,而不会继承原型上属性;可否Person.prototype.call(this)【答案: 不行, 因为call是函数方法】
Person.prototype.getPersonAge  = function() {
}

function Student(name, age){
    // 继承 Person
    Person.call(this, name, age);
    // Person.apply(this, [name, age]);
}
let zhangsan = new Student("zhangsan", 22);
zhangsan.sayName();    // zhangsan

也会有一个问题:子类无法继承父类定义在原型身上的属性和方法。 ,属性和方法都需要在构造函数内部定义。但是这样函数的复用就无从谈起了,并且每个对象实例都会保存相同的方法,这种方式也会造成内存的浪费。考虑到这些问题,借用构造函数的技术也是很少单独使用的。

  1. 遍历继承(也叫拷贝继承, 冒充继承): 其实就是遍历父类实例,拿来给子类

  2. 组合(混合)继承: 有时候也叫做伪经典继承,指的是将原型链和借用构造函数的 技术组合到一块,从而发挥二者之长的一种继承模式。实现的思路就是:使用原型链实现对原型身上的方法的继承,同时通过借用构造函数来实现对实例属性的继承。

    function Person(name, age){
    this.name = name;
    this.age = age;
    }
    Person.prototype.sayName = function(){
    console.log( this.name );
    }
    // 通过借用构造函数继承实例的属性
    function Student(name, age){
    Person.call(this, name, age);
    }
    // 通过原型链继承原型的方法
    Student.prototype = new Person();
    let zhang = new Student("zhangsan", 22);
    zhang.sayName();

    问题: 调用两次父类构造函数

    优化型

  3. 中间件继承 子类的私有实例: Parent.call(this, ...arguments) 子类的共享实例: Child.prototype = Parent.prototype

7 Es 6 Class-extends继承 区别: es5继承: 实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。 不能继承原生对象Array... es6 的继承机制完全不同: 实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this。 可以继承原生对象Array...

class A extends B {
  constructor(...arg) {
     // 此处调用this报错
     super(...arg) // A.prototype.constructor.call(this)
     // 可以调用this了
   } 
}

es5每个对象有proto属性, 每个函数有protoype属相 Class 作为构造函数的语法糖,同时有prototype属性和proto属性,因此同时存在两条继承链。 Child.proto === Parent 表示构造函数的继承,总是指向父类构造函数 : child作为对象 child.prototype.proto === Parent.prototype 表示实例方法的继承,指向父类的原型 : child作为构造函数 实现原理

Object.setPrototypeOf(Child.prototype, Parent.prototype);
Object.setPrototypeOf(Child,  Parent);

image image

Hibop commented 6 years ago

重新理解JS的6种继承方式: http://www.cnblogs.com/ayqy/p/4471638.html

Hibop commented 6 years ago
function Fun(){
    // 私有属性
    var val = 1;        // 私有基本属性
    var arr = [1];      // 私有引用属性
    function fun(){}    // 私有函数(引用属性)

    // 非原型实例,私有属性
    this.val = 1;               // 实例私有基本属性
    this.arr = [1];             // 实例私有引用属性
    this.fun = function(){};    // 实私有例函数(引用属性)
}

// 原型共享属性
Fun.prototype.val = 1;              // 原型基本属性
Fun.prototype.arr = [1];            // 原型引用属性
Fun.prototype.fun = function(){};   // 原型函数(引用属性)