javascript面向对象与原型

昨天我们讲了在面向对象中建立对象的几种体式格局

  • 工场形式
  • 组织函数形式

工场形式建立的对象,像工场一样来建立对象,建立的每一个对象都是经由过程new Object()来建立的,原型直指Object()
组织函数好像不错,但有的时刻我们须要对属性和要领举行修正,属性vue的同砚应当都遇到过这类状况,我们须要声明一些全局变量,我们平常这么做

//封装全局的ajax要求
  Vue.prototype.$http = function (url, options) {
      //部份代码省略
    return fetch(url, options)
  }
    // 注入 全局的wxSDK
 Vue.prototype.$wx = Wx

这时刻就用到了原型
我之前就用了大批篇幅讲过javascript的原型,此次遇到了面向对象,换个角度再次议论

原型形式建立对象

我们建立的每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用处是包括能够由特定范例的一切实例同享的属性和要领。
运用原型对象的优点是能够让一切对象实例同享它所包括的属性和要领。
也就是说,不必再组织函数中定义对象的实例信息,而是将这些属性和要领增加到原型对象中
一个🌰:

function Hero() {}
Hero.prototype.name = "欧阳锋"
Hero.prototype.nickname = "西毒"
Hero.prototype.doSth = function () {
    console.log('进修九阴真经');
}
const hero1 = new Hero()
console.log(hero1.name); //=>欧阳锋
console.log(hero1.nickname); //=>西毒
hero1.doSth() //=>进修九阴真经

const hero2 = new Hero()
console.log(hero2.name); //=>欧阳锋
console.log(hero2.nickname); //=>西毒
hero2.doSth() //=>进修九阴真经

我们看下hero1

console.log(hero1);

《javascript面向对象与原型》
我们能够经由过程对象实例接见保存在原型中的值,然则我们不能经由过程对象实例重写原型中的值,强迫的重写也能够

function Hero() {

}
Hero.prototype.name = "欧阳锋"
Hero.prototype.nickname = "西毒"
Hero.prototype.doSth = function () {
    console.log('进修九阴真经');
}
const hero1 = new Hero()
hero1.__proto__.name='黄药师'
console.log(hero1.name);//=>黄药师
const hero2 = new Hero()
console.log(hero2.name);//=>黄药师

这么做就是修正了原型链,经由过程原型建立的其他实例也会同步变动,如许不是我们所愿望的效果
怎么办?

实例属性屏障同名的原型属性

在实例中增加属性,使这个属性和原型中的属性同名,这个属性会屏障掉(也能够理解为覆蓋掉)原型中的谁人属性
继承👆的🌰

function Hero() {

}
Hero.prototype.name = "欧阳锋"
Hero.prototype.nickname = "西毒"
Hero.prototype.doSth = function () {
    console.log('进修九阴真经');
}
const hero1 = new Hero()
const hero2 = new Hero()
hero1.name="黄药师"
console.log(hero1.name);//=>黄药师
console.log(hero2.name);//=>欧阳锋

我们看下hero1

console.log(hero1);

《javascript面向对象与原型》
黄药师在实例中,欧阳锋在原型中,
我们接见hero1.name,会先在实例上去搜刮name属性,实例上存在name属性,就返回实例上的name属性,住手搜刮。
我们再去接见hero2.name,一样的会在实例上举行搜刮name属性,然则没搜到,继承顺着原型链举行搜刮,搜到了,返回原型中的name属性。
我们在原型中增加一个属性,这个属性会屏障掉原型中的同名属性,也就是说会阻挠我们接见原型中的同名属性,然则不会修正,假如我们把这个属性设置为null,会怎样呢?

//部份代码省略
const hero1 = new Hero()
const hero2 = new Hero()
hero1.name=null
console.log(hero1.name);//=>null(来自实例)
console.log(hero2.name);//=>欧阳锋(来自原型)

所以说,就算设置为null,结论是和上面是雷同的,只要在实例上存在这个要接见的属性,就会住手搜刮
实例中的属性我不想要了怎么办,设置null也无效,运用delete删除

//部份代码省略
const hero1 = new Hero()
const hero2 = new Hero()
hero1.name=null
delete(hero1.name)//删除实例中的属性
console.log(hero1.name);//=>欧阳锋(来自原型)
console.log(hero2.name);//=>欧阳锋(来自原型)

推断属性属于实例照样原型

有个内置要领hasOwnProperty()用来推断属性是不是来自于实例,属于实例则返回true,不然false

//部份代码省略
const hero1 = new Hero()
const hero2 = new Hero()
hero1.name='黄药师'
// console.log(hero1.name);
// console.log(hero2.name);
console.log(hero1.hasOwnProperty('name'));//=>true
console.log(hero2.hasOwnProperty('name'));//=>false

另有一个in操作符,假如对象能接见到指定属性就返回true

//部份代码省略
const hero1 = new Hero()
const hero2 = new Hero()
hero1.name='黄药师'
console.log('name' in hero1);//=>true
console.log('name' in hero2);//=>true

我们将in和hasOwnProperty()连系在一起,封装一个要领用来推断属性来自原型照样实例

const hero1 = new Hero()
const hero2 = new Hero()
hero1.name = '黄药师'
//true=>来自原型
//false=>来自实例
function attrFromProto(obj, attr) {
    return !obj.hasOwnProperty(attr) && (attr in obj)
}
console.log(attrFromProto(hero1, 'name'));//=>false(来自实例)
console.log(attrFromProto(hero2, 'name'));//=>true(来自原型)

原型形式建立对象的简化版

👆我们建立对象是如许的

function Hero() {

}
Hero.prototype.name = "欧阳锋"
Hero.prototype.nickname = "西毒"
Hero.prototype.doSth = function () {
    console.log('进修九阴真经');
}

我能反复的写prototype,我们连系对象字面量简化一下

function Hero() {

}
Hero.prototype = {
    name: "欧阳锋",
    nickname: "西毒",
    doSth: function () {
        console.log('进修九阴真经');
    }
}

经由过程原型形式建立对象注意事项

在原型中增加公有要领是值得勉励的,类似于我们在vue中增加全局ajax,增加一下基础范例的变量也能够,然则当增加援用范例的属性时刻题目就涌现了

function Hero() {

}
Hero.prototype.name = "欧阳锋"
Hero.prototype.nickname = "西毒"
Hero.prototype.skill = ["灵蛇拳", "神驼雪山掌"]
Hero.prototype.doSth = function () {
    console.log('进修九阴真经');
}
const hero1 = new Hero()
const hero2 = new Hero()
hero1.skill.push('灵蛇杖法')
console.log(hero1.skill);//=>["灵蛇拳", "神驼雪山掌", "灵蛇杖法"]
console.log(hero2.skill);//=>["灵蛇拳", "神驼雪山掌", "灵蛇杖法"]

我只在hero1实例中push了“灵蛇杖法”,效果影响到了hero2,
当在实例对象上增加援用范例时要分外警惕
本日就到这里,来日诰日不见不散
收集整理了一些电子书,有须要的,在民众号背景复兴“电子书”即可领取
《javascript面向对象与原型》

原文链接

《javascript面向对象与原型》

    原文作者:陌上寒
    原文地址: https://segmentfault.com/a/1190000017399841
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞