Javascript 原型链和对象

科技 2017-08-21 0 条评论 访问: 2,228 次

Z.jpg

Javascript 创建“类”和对象

接触过像 C++ Java 这样的编程语言,对面向对象编程一定不陌生。面向对象编程的两个核心是类和对象。
类是一种数据结构(事物)的描述、生成对象的模板,而对象是根据描述创建的实体。
如果说面向对象,Javascript 则更加“忠诚”,因为它根本就没有类,所谓“类”只是一个构造器,一个函数。在 JS 中,万物皆为对象,函数也是对象。JS 可以模拟类和对象的行为,让编程就像面向对象编程一样。JS 面向对象编程的实现是用函数,作用域劫持和闭包“凑活”出来的。说了这么多学院理论,Let's make our hands wet!

创建一个学生类,有姓名和学号属性和打招呼(say)方法

function Student(name, id) {
    this.name = name
    this.id = id
}
Student.prototype.say = function() {
    console.log('Hello, I am ' + this.name)
}
var jack = new Student('Jack', 1210)
jack.say() //Hello, I am Jack

让我们看看这七句话都做了哪些事。

在 JS 中,每个对象都有一个__proto__内置属性,这里面存放了一个指向对象原型的引用(指针),此例中是Student.prototype.prototype可以认为是Student对象的一个属性。对象原型这个属性 Student.prototype 下面可以挂一些公共方法或者属性(可以先理解为静态方法,静态成员变量)
new Student 中的new都做了那些事情

  1. 创建一个空对像 var obj = {}
  2. 将刚才创建对象pbj的__proto__属性设置为Student.prototype obj.__proto__ = Student.prototype
  3. Student.call(obj)Student的作用域劫持到obj对象上并执行,此时Student函数里面的this指向obj
  4. obj返回 return obj

jack 变量接收返回的 obj
jack.say()
当访问一个对象的属性或者方法时,查找顺序依据原型链,jack的原型链是
jack--->Student.prototype--->Object.prototype--->null
jack对象中并没有say这个方法,于是向上查找,在其对象原型(通过__proto__属性找到对象原型)下找到该方法的定义然后执行

Q & A

为什么不把方法放到Student构造器里面?

这样每当创建一个实例,就会生成一个say方法(或者说属性)这些say方法的逻辑都一样,但是却占用了多份空间,对性能产生影响。
var jessie = new Student('Jessie', 14512)
jack.say === jessie.say //false

可不可以手动改变一个对象的__proto__

不要手动这样做!不要手动这样做!不要手动这样做!

jack.__proto__.__proto___

jack.__proto__Student.prototypeStudent.prototype.__protoObject.prototype。熟悉 Java 的同学可能知道,Java 里面所有的类都继承自 Object 类,Object 是所有类的老祖宗。而Object.prototype是所有对象的原型,换句话说,所有对象都可以调用Object.prototype下面的方法。
例如Student.prototype.isPrototypeOf(jessie)//true
其中isPrototypeOf(jessie)就是Object.prototype下面的方法

结束语

Javascript 是一门很灵活也有很多坑的语言。本身的设计也有不少缺陷。如果有些灵活过头的特性,不如把它加入黑名单,不去使用它,比如手动修改__proto__这种做法。在 Javascript 中很多原则是人为规定,并不是强制的。在写代码的过程中尽量遵守,以免造成麻烦。


除非注明,嗯VIEW文章均为原创,转载请以链接形式标明本文地址
本文地址:https://www.umview.com/javascript-prototype-obj

本文由 Mark 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

还不快抢沙发

添加新评论