Javascript 构造函数、原型对象、实例之间的关系

复制代码
# Javascript 构造函数、原型对象、实例之间的关系

# 创建对象的方式
# 1.new object()   缺点:创建多个对象困难
var hero = new Object();    // 空对象
hero.blood = 100;
hero.name = '刘备';
hero.weapon = '';
hero.attack = function () {
  console.log(this.weapon + ' 攻击敌人');
}

# 2.对象字面量    缺点:创建多个对象困难
var hero = {
  blood: 100,
  name: '刘备',
  weapon: '',
  attack: function () {
    console.log(this.weapon + ' 攻击敌人');
  }
}

# 3.工厂函数 创建多个对象    缺点:无法获取具体类型(typeof 返回结果是Object)
function createHero(name, blood, weapon) {
  var o = new Object();
  o.name = name;
  o.blood = blood;
  o.weapon = weapon;
  o.attack = function () {
    console.log(this.weapon + ' 攻击敌人');
  }
}
hero = createHero('刘备', 100, '')

# 4.通过构造函数来实现    解决了工厂对象遗留的问题
function Hero(name, blood, weapon) {
  this.name = name;
  this.blood = blood;
  this.weapon = weapon;
  this.attack = function () {
    console.log(this.weapon + ' 攻击敌人');
  }
}
var hero1 = new Hero('刘备', 100, '');
var hero2 = new Hero('关羽', 100, '');
console.log(hero1.constructor === Hero);      # 而constructor可以改变,所以不建议这么用
console.log(hero1 instanceof Hero);        # 这样看它是否是Hero的对象
console.log(hero1.attack === hero2.attack);    # ===比较地址。这里返回False
# 问题一:new Hero具体干了啥?
# .首先会在内存中创建一个空对象
# ..设置构造函数的this,让this指向刚刚创建好的对象
# ...执行构造函数中的代码
# ....返回对象
# 问题二:为什么attack函数不是同一个,却又能通过this去访问实例属性?
# new的时候会执行构造函数中的代码,也就是会执行function ()的时候会创建自己的一个空this对象,所以Hero不同实例的attack其实不是同一个。
# 而调用的时候是通过hero1.attack()和hero2.attack()调用的,这时候this代表的是hero1\hero2,所以能通过this.weapon来调用。
# 问题三:如果需要通过Hero构造函数构造几十上百个对象,那么attack方法不是会浪费很大的资源?
# 解决方案一:将attack声明为全局的,在Hero构造的时候赋值给this.attack。这样的弊端是,当构造方法一多的时候,方法名容易重名。
# 解决方案二:通过构造函数的原型对象去实现。

# 每一个构造函数都有一个属性prototype,也就是原型对象。通过同一个构造函数new出来的实例共享一个原型对象中的属性。
function Student(name, age, sex) {
  this.name = name;
  this.age = age;
  this.sex = sex;
}
Student.prototype.sayHi = function () {
  console.log('大家好,我是' + this.name)
}
var s1 = new Student('lilei', 18, '');
var s1 = new Student('hmm', 18, '');
s1.sayHi();s2.sayHi();
# 如果原型对象和构造函数中都有sayHi方法的话,优先调用构造函数中的sayHi方法。

# Student构造函数、Student原型对象、Student实例/对象之间的关系
# 1.每个构造函数中都有一个prorotype原型对象
# 2.prorotype原型对象中有一个constructor属性,它指向的是它本身所属的构造函数
# 3.每个实例都有一个__proto__属性,它指向的是构造函数的prototype原型对象
# 4.因为每个实例都有一个__proto__属性,所以Student构造函数的构的原对象也有__proto__,它就是Object的原型对象
# 5.Object的原型对象的__proto__属性是空
# 得出结论:
# .当获取实例的属性的时候,先从自身直接属性中获取值,如果没有就去__proto__原型对象中获取,原型对象中也没有的话就到Object原型对象中去找,再没有就报错,因为原型对象的__proto__是null。
# ..注意:在实例中设置属性的时候不会影响原型对象。因为设置的时候实例本身不具备属性是直接新增属性,并不会修改原型中的属性。
# ...你可以直接通过实例.constructor属性可以判断实例是属于哪个构造函数的。
# 如果需要在原型对象中设定多个函数的话,你可以这么做
function Student(name, age, sex) {
  this.name = name;
  this.age = age;
  this.sex = sex;
}
Student.prototype = {
  constructor: Student,    # 这里必须设定,不然就没办法找到所属构造函数
  sayHi: function () {
    console.log('大家好,我是' + this.name)
  }
}
复制代码

 

posted @   看一百次夜空里的深蓝  阅读(112)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示