Javascript类和继承

Javascript中的‘类’

Javascript中并没有严格意义上的类。ES5中通过使用首字母大写的方法来模拟类。这个首字母大写的方法也被称为构造函数,其是一个函数。
构造函数前面用关键字new,则创建一个新的空对象,并用这个新对象调用这个函数。

function Person (name) {
  this.name = name;
}  
var per1 = new Person('bob');

其实方法也是对象,方法都是由Function构造函数创建的,Function由它本身创建。

三个概念

  • 构造函数:也是一个函数,一般和关键字new配合使用,你单独调用也会不报错。其本身也是一个对象。
  • 原型对象 : 构造函数的prototype属性指向的就是原型对象。
  • 实例对象 : new 关键字新创建的对象,new关键字和构造函数一起用,新创建的对象调用构造函数,构造函数里通过this关键字引用实例对象,
    通过this关键字初始化实例对象。

如果构造函数里显示的返回一个对象,我们声明的实例对象就是返回的这个

function OBJ(){
  return {name : 1}
};
var other = new OBJ(); 
other.name;  // 1

//other的构造函数为Object , 如果返回的是一个别的构造函数创建的实例对象,other就是指向这个实例对象

一个例子

function Person(name){
  this.name = name
}
var per = new Person("someone");

在这个例子中,Person是构造函数,是一个函数对象,是对象就会有构造函数(Object.prototype对象除外,它是唯一没有原型和构造函数的对象)
Object.prototype instanceof Object // false 结果很有趣
函数对象的构造函数都是Function , Object也是函数对象,所以 Object的构造函数也是Function.

  • 对象的constructor属性指向其对应的构造函数
    Person.constructor // ƒ Function() { [native code] }
    Object.constructor // ƒ Function() { [native code] }
    Function也是构造函数对象,所以 Function instanceof Function 为true 同时 Function instanceof Object 也为true 而Object instanceof Function也为true 结果很有趣。
  • 实例对象的proto属性是浏览器实现的一个指向该对象原型对象的属性。
    Function.____proto____ === Function.prototype
    Function的____proto____指向创建Function的函数的prototype,Function由它自己创建。
    Objecet.prototype.___proto____ === null

上面的例子,解释器会为Person创建一个初始的prototype,这个原型对象中有个constructor属性指向构造函数,在我们给Person指定自定义的对象时,自定义的对象是没有自己的constructor属性的(会继承),除非我们手动添加

实现继承

  • 给实例对象的原型对象即构造函数的prototype添加方法,或属性(一般不建议添加属性),所有的实例对象都会继承这些方法和属性,而且这些方法和属性在实例对象中都是可访问的。给构造函数添加方法和属性能模拟实现类方法和类字段

  • 当通过构造函数创建对象时,对象所有的属性值将会被复制给新的对象。但由于prototype是一个引用类型的变量,存储的是对象的地址,因此prototype中的所有属性值将会被该函数创建的所有对象共享,若一个对象修改了prototype中的某个属性,那所有对象prototype属性都会发生修改。
    因此,prototype属性适合存储不变的属性,如函数;构造函数的普通属性适合存储基本类型的属性;而对象无论存储在哪里效果都一样。

  • 此外,将函数存储在prototype中可以达到节约内存的功效,不论创建多少对象,该原型对象的函数在内存中只有一份。

  • 在实例对象中通过obj.继承来的方法/属性 = somevalue 是无法修改原型对象的方法或属性的,因为在调用对象中的属性或者方法时,首先会在当前对象中查找是否有该属性,若无则依次在该对象的原型链中找,如果到最后还找不到则返回undefined。obj.继承来的方法/属性 = somevalue 会给当前对象创建一个和继承来的属性同名的属性,并且在当前对象中调用会覆盖掉继承来的属性。

function Student(id){
this.id = id
}

根据现实逻辑,Student是Person的一类
所以Student的实例应该有Person的特征
继承是通过prototype表现的,所有类的实例对象都会继承类(构造函数)protptype的属性和方法。prototype一定是个对象
Student.prototype = inhert(Person.prototype) || new Person();
Student.prototype.constructor = Student //这一句是指定Student实例的构造函数的,如果不指定,不会默认生成,而是使用继承来的(这里就是Person)

function inherit(obj){
    if(obj == null || (typeof obj !== "object" && typeof obj !== "function")){
        throw TypeError();
    }
    if(Object.create) return Object.create(obj);   //新建一个对象,对象构造函数的prototype为obj
    var f = function(){};
    f.prototype = obj;
    return new f();
}

关于实例对象的constructor

  • ① var obj = {}; || var obj = new Object();
    obj的构造函数是Object , obj.constructor: Object
    obj的constructor是继承Object.prototype的,obj.hasOwnProperty(constructor) //false

  • ② function Person(){
    }
    var obj2 =new Person();
    obj2.constructor : Person
    obj的constructor是继承Person.prototype的。
    Person.prototype : {constructor : Person} //解释器创建
    解释器会为Person创建一个初始的prototype,这个原型对象中有个constructor属性指向构造函数,在我们给Person的prototype指定自定义的对象时,自定义的对象会有一个继承自它的原型对象的constructor属性,如果要Person的实例对象的constructor正确的指向它的构造函数,需要我们手动添加Person.prototype.constructor = Person。
    例如:如果Person.prototype = {name : 'otherobj'};
    var otherobj = new Person(); otherobj.constructor : Object

  • ③ var obj3 = Object.create(obj2) // 创建一个对象,obj3的原型对象为obj2
    obj3.constructor //Person
    obj3.constructor.prototype // obj2
    obj3.constructor.prototype.constructor.prototype //{constructor : Person}
    obj3.constructor.prototype.constructor.prototype.constructor.prototype //Object.prototype

  • ④function Student(){
    }
    Student.prototype = new Person();
    var obj4 =new Student();
    obj4.constructor //Person
    Student.prototype.constructor = Studnet;//手动设置

//下面两种错误的继承
Student.prototype = Person.prototype //Student和Person一样了
Student.prototype = Person //Person这个函数对象被当作prototype了

var otherCon = Person;
obj4 instanceof otherCon //true instanceof是检测对象的继承关系而不是构造函数
函数有个name属性,可以用来看构造函数的name

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

推荐阅读更多精彩内容