js 对象

特权方法、公有方法、静态方法


function Animal(name) {  // Animal是一个基于函数的“类”
  var _name = name;        //私有属性
    //特权方法
    this.getName = function() {
        return _name;
    };
    this.setName = function(name) {
        _name = name;
    };
}

Animal.type = function() {
  console.log(this + 'is a private static function')  // Animal的私有静态方法
}

Animal.prototype.speak = function() {  // 定义一个原型方法 在js中也叫做公有方法  也是公有静态方法, 所有的Animal实例共享一份数据
  console.log(this.name + ' makes a noise.');
}

var an1 = new Animal()
var an2 = new Animal()

console.log(an1.getName === an2.getName)  // false
console.log(an1.speak === an2.speak) // true
console.log(an1.type) // undefined
console.log(an1.speak) // function() ……

如例子所示:Animal是一个基于函数的“类”,an1和an2都是一个Animal的对象实例

  1. 特权方法:每个对象独有的方法,每次创建一个实例对象,都会在内存中保存一份该特权方法,特权方法可以访问"类"的私有成员
  2. 公有方法:所有实例对象共享的一份属性和方法,只会在内存中保存一份
  3. 静态方法:可以定义在原型对象中,也可以定义在类上。定义在类上面的方法是类私有的,实例对象无法获取,定义在原型中的方法,实例对象可以获取
  4. 定义在函数内部的方法和属性是私有的,在函数外部获取不到,定义在函数上(如Animal.type)的方法和属性也是私有,不同之处是可以在外部通过Animal.type获取到

tips:将实例对象的属性存储在实例对象中,公有的属性存储在原型中,可以避免创建许多分公有的数据和方法,浪费存储空间(大部分情况下,方法都是公有的,存放在prototype中)

prototype和__proto__

如下所示,定义一个Animal类,Dog和Cat继承自Animal


function _inherits(subClass, superClass) {
  subClass.prototype = Object.create(
    superClass && superClass.prototype,
    {
      constructor: { value: subClass, enumerable: false, writable: true, configurable: true
    }
  });
  subClass.__proto__ = superClass
}

function Animal(name) {  // Animal是一个基于函数的“类”
}


var an1 = new Animal()

var Dog = function (_superClass) {
 _inherits(Dog, _superClass)
  function Dog() {
    return _superClass.apply(this, arguments)
  }
  return Dog
}(Animal)

var Cat = function (_superClass) {
 _inherits(Cat, _superClass)
  function Cat() {
    return _superClass.apply(this, arguments)
  }
  return Cat
}(Animal)


var dog1 = new Dog()
var cat1 = new Cat()

console.log(an1.__proto__ === Animal.prototype)
console.log(Dog.__proto__ === Animal)
console.log(Cat.__proto__ === Animal)
console.log(dog1.__proto__ === Dog.prototype)
console.log(cat1.__proto__ === Cat.prototype)
console.log(Dog.prototype.__proto__ === Animal.prototype)
console.log(Cat.prototype.__proto__ === Animal.prototype)
console.log(an1.constructor === Animal)
console.log(cat1.constructor === Cat)
console.log(dog1.constructor === Dog)

根据上述的输出,Animal、Dog、Cat之间的关系,以及他们的原


js 对象_第1张图片
2 Circles (1).png

型关系如图所示:

总结出:

  1. 每个函数都有一个属性prototype,指向实例对象的原型
  2. 每个原型对象都有一个constructor,指向构造方法
  3. 每个对象都有一个__proto__,这项该对象的原型对象
    a. 对象可以继承其原型对象中的方法和属性
    b. __proto__有些浏览器不支持(开发中最好不要使用 __proto__),Object.getPrototypeOf(obj)是es5检索对象的原型(proto)的标准方法
    c. 每个对象都有一个 __proto__指向它的原型,这就是原型链(prototype chain)
    d.instanceof, object.instanceof(constructor),判断Object的原型链中是否存在constructor.prototype,表示一直继承关系

继续

console.log('\n', Animal.__proto__ === Function.prototype)
console.log(Animal.prototype.__proto__ === Object.prototype)
console.log(Function.__proto__ === Function.prototype)
console.log(Function.prototype.__proto__ === Object.prototype)
console.log(Object.__proto__ === Function.prototype)
console.log(Object.prototype.__proto__ === null)
js 对象_第2张图片
2 Circles (2).png

继承

如上栗所示,Dog类继承Animal类,根据图中继承的关系,需要执行以下步骤

  1. Dog继承Animal:Animal.apply(this, arguments)this指向Dog对象
  2. 设置Dog.prototype继承Animal.prototype,并且设置Dog.prototype的constructor指向Dog函数:
Dog.prototype = Object.create(
    Animal && Animal.prototype,
    {
      constructor: {
        value: subClass,
        enumerable: false,
        writable: true,
        configurable: true
    }
  });
  1. 设置Dog.__proto__ = Animal
    上栗babel的extends源码
  2. \_classCallCheck函数,判断生成的对象原型链上是否存在Constructor.prototype,避免把构造函数当做一般函数使用,比如把直接调用Animal()就会报错'Cannot call a class as a function'
  3. \_inherits函数,设置subClass. prototype.__proto__ = superClass以及subClass. prototype. constructor = constructor,设置subClass.__proto__ = superClass,.__proto__ 是非标准方法,浏览器不支持的时候使用Object.setPrototypeOf(subClass, superClass)
'use strict';

function _possibleConstructorReturn(self, call) {
  if (!self) {
    throw new ReferenceError('this hasn\'t been initialised - super() hasn\'t been called');
  }
  return call && (typeof call === 'object' || typeof call === 'function') ? call : self;
}

function _inherits(subClass, superClass) {
  if (typeof superClass !== 'function' && superClass !== null) {
    throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass);
  }
  subClass.prototype = Object.create(superClass && superClass.prototype,
    { constructor: { value: subClass, enumerable: false, writable: true, configurable: true }
  });
  if (superClass) {
    Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
  }
}

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError('Cannot call a class as a function');
  }
}

var Animal = function Animal(name) {
  _classCallCheck(this, Animal);

  this.name = name;
};

var Dog = function (_Animal) {
  _inherits(Dog, _Animal);

  function Dog() {
    _classCallCheck(this, Dog);

    return _possibleConstructorReturn(this, (Dog.__proto__ || Object.getPrototypeOf(Dog)).apply(this, arguments));
  }

  return Dog;
}(Animal);

你可能感兴趣的:(js 对象)