JS 原型那点事
众所周知,JS与Java中面向对象的实现是不一样的,当从Java中的类到接触JS中的原型时,一上来就很容易搞得一头雾水,在网上搜索相关的内容——如原型链、prototype、__proto__等内容时,搜索出的文章更是把人往坑里带。当阅读了大量的官方、非官方的文章之后,总算是有点见解了。在此就记下我关于JS中原型的见解。
Java中的面向对象
因为Java中的面向对象很好理解,所以首先从Java的面向对象说起。
Java中的类可以看成是要创建对象的模版,其包含一些属性和方法,方法中有一个特别的方法是构造函数。
创建对象就是调用了构造函数——从类生成了一个对象,然后对象就具有了类中声明的属性和方法。
JS中的原型链
JS面向对象是基于原型链实现的,虽然ES6中新增了class用于声明类的关键字,但它本质上仍然是基于原型链的。
JS中创建对象有两种方法,一个是使用语法结构创建对象,如: var o = { a: 1 } ,一个是使用构造器创建对象,如: var person = new Person('John', 23) 。
下面主要解释第二种,使用构造器创建对象的方法。构造器是JS中函数的一种调用方法(其他还有作为函数调用、作为对象的方法调用、通过apply或call调用等)。
构造器(constructor)和原型(prototype)
Java中创建对象的模版是类,而JS中是原型(prototype)。Java中类的构造函数,在JS中就是以构造器方式调用的函数。
// 声明一个 Person 函数 function Person(name, age) { this.name = name; this.age = age; } // JS中的函数默认带有 prototype 属性,可以把 prototype 想象成Java中的类,可以在其中定义属性和方法 Person.prototype.sayName = function () { console.log('My name is', this.name); } // 此时, Person.prototype 上有两个方法 constructor 和 sayName // constructor 就是这个“类”的“构造方法”,即上面定义的 Person 函数 // console.log(Person.prototype.constructor === Person) // true // sayName 是自定义的一个方法 // 创建对象,在函数前使用 new 关键字, Person 函数就构造器创建了一个新的 person 对象 var person = new Person('John', 23)
原型链(__proto__)
未完待续。。。
最后
本文主要是借助Java中的面向对象理解JS中的原型,但两者还是无法完全类比,详细信息可继续参考 继承与原型链 | MDN