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之间的关系,以及他们的原


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)
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);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,298评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,701评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,078评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,687评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,018评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,410评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,729评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,412评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,124评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,379评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,903评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,268评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,894评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,014评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,770评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,435评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,312评论 2 260

推荐阅读更多精彩内容

  • 内容来自《JavaScript高级程序设计》第三版第6章第3节 原型链 ECMAScript中描述了 原型链的概念...
    angelwgh阅读 217评论 0 0
  • 对象:由多组无序属性组成的数据结构 (键值对) 成对出现:属性名 属性值字面量 简单对象也存在构造函数 (如:...
    月光在心中阅读 300评论 0 0
  • 对象: 1. 对象中包含一系列的属性,这些属性是无序的。 2. 每个属性都有一个字符串key和对应的value;(...
    一树青枫阅读 330评论 0 1
  • 官方中文版原文链接 感谢社区中各位的大力支持,译者再次奉上一点点福利:阿里云产品券,享受所有官网优惠,并抽取幸运大...
    HetfieldJoe阅读 2,954评论 4 14
  • 人与人之间的差别,大于人与猪的差别。前者的基因差异是恒定的,可量化的;后者则完全超出想象,无法预测。 我们可以学唱...
    Sunny夕夕阅读 274评论 0 2