Yang03 / blog

0 stars 0 forks source link

javascript 继承 #9

Open Yang03 opened 8 years ago

Yang03 commented 8 years ago

es5 class

es5中是不存在class 的,但是我们可以通过构造函数来模拟

    function Point(x, y) {
        this.x = x;
        this.y = y;
    }

    Point.prototype.toString = function() {
        console.log('x:' + this.x + ' y:' + this.y);
    }

    var p = new Point(4, 5);
    p.toString() // x:4 y:5

    p.__proto__ === Point.prototype // true

当一个对象被创建时,它的 proto 属性指向它的构造函数的prototype属性,改变proto 属性的值同时也会改变内部属性的值,除非该对象是不可扩展的.

es6 中的class

    class Point {
        constuctor(x, y) {
            this._x = x;
            this._y = y; 
        }
        toString() {
            console.log('x:' + this._x + ' y:' + this._y); 
        }
    }
    var  p = new Point(4,5);
    p.toString(); // x:4 y:5
    typeof Point  // function es6中class 其实是一个特殊函数
    // Person()  Class constructor a cannot be invoked without 'new'

class 没有hoisted(提升),原因是语义阶段无法解析到extends的内容,因为extends 后面可能可以是class表达式

es6 中如何定义class

    new Point() //ReferenceError
    class Point {}

    var Point = class {

    }
    //class body 只包含constructor, static methods, prototype methods

class 声明的对象必须使用new 实例化

new是怎么工作的呢?

如:

    function New(fn) {
        var n = {'__proto__', fn.prototype}
        return function() {
           fn.apply(n, arguments);
           return n;                 
        }
    }

es5里面的函数继承

    function Point(x, y) {
        this.x = x;
        this.y = y;
    }

    Point.prototype.getSometing = function() {
        console.log('x:' + this.x + ',y:' + this.y);
    }

    function ColorPoint(x, y, color) {
        Point.apply(this, [x, y]);
        <!-- this.x = x;
        this.y = y;-->
        this.color = color; 
    }

    ColorPoint.prototype = new Point();
//子类的原型指向父类的实例
    ColorPoint.prototype.constructor = ColorPoint;
//构造函数指回自己

    //ColorPoint.prototype = Object.create(Point.prototype);

    var cp = new ColorPoint(4, 5);
    cp.getSometing();

    cp.hasOwnProperty(getSometing) //false

    ColorPoint.prototype.getSometing = function() {
        console.log('x:' + this.x + ',y:' + this.y + ',color:' + this.color);
    }
    var cp2 = new ColorPoint(5, 6, 'red')    
    cp2.getSometing()

当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止。

到查找到达原型链的顶部 - 也就是 Object.prototype - 但是仍然没有找到指定的属性,就会返回 undefined。 用代码描述:

    function getProperty(obj, prop) {
    if (obj.hasOwnProperty(prop))
        return obj[prop]

    else if (obj.__proto__ !== null)
        return getProperty(obj.__proto__, prop)

    else
        return undefined
    }

hasOwnProperty 是 JavaScript 中唯一一个只涉及对象自身属性而不会遍历原型链的方法。 Object.getPrototypeOf 返回指定对象的原型

ColorPoint.prototype = new Point(),这种方式会多执行一遍父类的构造函数,并且会在子类的原型上多定义一组父类对象的实例属性,直接对constructor赋值的话,会让它重新变成一个可枚举的属性, Object.create(Point.prototype); //方法创建一个拥有指定原型和若干个指定属性的对象

Child.prototype = Object.create(Parent.prototype, 'constructor', {
     value: Child,
     enumerable: false,
     writable: true,
     configurable: true
});

es6 的继承

    class Point {
        constructor(x, y) {
            this.x = x;
            this.y = y;
        }
        getSometing() {
              return '(' + this.x + ', ' + this.y + ')';
        }
    }

    class ColorPoint extends Point {
        constructor(x, y, color) {
            super(x, y); 
            this.color = color;
        }
        getSometing() {
            console.log(super.getSometing() + this.color);
        }
    }

    var cp2 = new ColorPoint(5, 6, 'red')    
    cp2.getSometing() // x:5, y:6, red

    //super 必须调用,不然会报错,必须在this关键字之前调用 

cp 的proto 指向ColorPoint的prototype ColorPoint 的prototype 指向Point