We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
function Person(nick, age) { // 构造函数Person this.nick = nick; this.age = age; } Person.prototype.sayName = function() { // 在构造函数的原型上定义一个sayName()的方法 console.log('我的名字是:' + this.nick); } var p1 = new Person('Jessica', 18); var p2 = new Person('Jay', 20); p1.sayName(); // 我的名字是:Jessica p1.sayName(); // 我的名字是:Jay p1.__proto__ === Person.prototype; // true p2.__proto__ === Person.prototype; // true Person.prototype.constructor === Person //true
需要注意的是:
请看下面的代码:
var arr = [1, 2, 3]; arr.valueOf(); // [1, 2, 3]
按照之前的理论,如果自身没有该方法,我们应该无Array.prototype对象里面去找,但是你会发现 arr.__proto__上根本就没有 valueOf 方法,那它是从哪里来的呢? 我们来看一下Array.prototype中__proto__的构成: 这里却有一个valueOf方法,为什么呢?
当试图访问一个对象属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,一次层层向上搜索,直到找到一个名字匹配的属性或者达到原型链的末尾。 查找 valueOf 的大致过程如下:
原型链的终点: Object.prototype.proto === null; // true 所以对于这种情况,整个原型链的查找过程是: arr ----> Array.prototype ----> Object.prototype ----> null 这就是我们常说的原型链,层层向上查找,最后还没有找到就返回undefined。
继承指的是一个对象直接使用另外一个对象的属性和方法。
由此可见,只要实现属性和方法的继承,就能达到继承的效果:
我们先创建一个Person类
function Person(name, age) { this.name = name; this.age = age; } // 方法定义在构造函数的原型上 Person.prototype.getName = function() { console.log(this.name); }
这个时候,我想创建一个Student类,我们希望它可以继承Person的所有属性,并且能够额外添加自己的特定属性;
function Student(name, age, grade) { Person.call(this, name, age); this.grade = grade; }
属性的继承是通过在一个类内执行另外一个类的构造函数,通过call指定this为当前执行环境,这样就可以得到另外一个类的所有属性。 我们实例化这个类来看一下:
var student1 = new Student('Jessica', '29', '100'); student1.name; // Jessica student1.age; // 29 student1.grade; // 100
显然,student1成功的继承了Person的属性(name和age)。
我们需要让Student从Person的原型对象里继承方法。我们要怎么做呢? 我们都知道类的方法都定义在prototype里,那其实我们只需要把Person.prototype的备份赋值给Student.prototype即可。
Student.prototype = Object.create(Person.prototype)
Student.prototype.constructor = Student;
我们整理一下,主要是prototype和constructor的问题。
Student.prototype = Object.create(Person.prototype); Student.prototype.constructor f Person(name, age) { this.name = name; this.age = age; } =================================== Student.prototype.constructor = Student; f Student(name, age, grade) { Person.call(this, name, age) { this.grade = grade; } }
所以,继承的最终方案是:
Student.prototype = Object.create(Person.prototype); Student.prototype.constructor = Student;
在原型链上查询属性比较耗时,对性能也存在一定的影响,试图访问不存在的属性时会遍历整个原型链。遍历对象时,每个可枚举的属性都会被枚举出来。要检查是否具有自己定义的属性,而不是原型链上的属性,就必须使用 hasOwnProperty 方法。该方法时JavaScript中唯一处理属性并且不会遍历原型链的方法。
每个对象都有一个 proto,它指向它的 prototype 原型对象,而 prototype 原型对象又具有一个自己的 prototype 原型对象,这样层层往上直到一个对象的原型 prototype 为 null,这个查询的路径就是原型链。
function Person (name, age) { this.name = name this.age = age } // 方法定义在构造函数的原型上 Person.prototype.getName = function () { console.log(this.name)} function Student(name, age, grade) { Person.call(this, name, age) this.grade= grade }
Student.prototype = Object.create(Person.prototype) Student.prototype.constructor = Student
The text was updated successfully, but these errors were encountered:
No branches or pull requests
参考文章
原型 prototype 和 proto
三者的关系图如下:
可能大家跟我一样,对于prototype以及__proto__会有疑问,他们到底有什么作用呢?
实例对象的__proto__指向构造函数的prototype,从而实现继承。prototype对象相当于特定类型所有实例对象都可以访问的公共容器。
需要注意的是:
原型链
请看下面的代码:
按照之前的理论,如果自身没有该方法,我们应该无Array.prototype对象里面去找,但是你会发现 arr.__proto__上根本就没有 valueOf 方法,那它是从哪里来的呢?
我们来看一下Array.prototype中__proto__的构成:
这里却有一个valueOf方法,为什么呢?
查找 valueOf 方法的过程
当试图访问一个对象属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,一次层层向上搜索,直到找到一个名字匹配的属性或者达到原型链的末尾。
查找 valueOf 的大致过程如下:
当然不会无限循环的找下去,原型链是有终点的,最后当找到Object.prototype时,Object.prototype.proto===null,就意味着查找结束了。一般的数组查找时对应的关系为(arr为一个实例对象,Array是此处arr的构造函数):
arr.proto === Array.prototype; // true
Array.prototype.proto === Object.prototype; // true
arr.proto.proto == Object.prototype; // true
原型链的终点:
Object.prototype.proto === null; // true
所以对于这种情况,整个原型链的查找过程是:
arr ----> Array.prototype ----> Object.prototype ----> null
这就是我们常说的原型链,层层向上查找,最后还没有找到就返回undefined。
JavaScript的继承
什么是继承?
继承指的是一个对象直接使用另外一个对象的属性和方法。
由此可见,只要实现属性和方法的继承,就能达到继承的效果:
属性如何继承?
我们先创建一个Person类
这个时候,我想创建一个Student类,我们希望它可以继承Person的所有属性,并且能够额外添加自己的特定属性;
定义Student的构造函数:
属性的继承是通过在一个类内执行另外一个类的构造函数,通过call指定this为当前执行环境,这样就可以得到另外一个类的所有属性。
我们实例化这个类来看一下:
显然,student1成功的继承了Person的属性(name和age)。
方法如何继承呢?
我们需要让Student从Person的原型对象里继承方法。我们要怎么做呢?
我们都知道类的方法都定义在prototype里,那其实我们只需要把Person.prototype的备份赋值给Student.prototype即可。
因为如果直接赋值,那会是引用关系,意味着修改Student. prototype,也会同时修改Person.prototype,如果子类继承后导致原来的父类变得可以修改了,这是极其不合理的。
我们整理一下,主要是prototype和constructor的问题。
所以,继承的最终方案是:
hasOwnProperty
在原型链上查询属性比较耗时,对性能也存在一定的影响,试图访问不存在的属性时会遍历整个原型链。遍历对象时,每个可枚举的属性都会被枚举出来。要检查是否具有自己定义的属性,而不是原型链上的属性,就必须使用 hasOwnProperty 方法。该方法时JavaScript中唯一处理属性并且不会遍历原型链的方法。
总结
原型链
每个对象都有一个 proto,它指向它的 prototype 原型对象,而 prototype 原型对象又具有一个自己的 prototype 原型对象,这样层层往上直到一个对象的原型 prototype 为 null,这个查询的路径就是原型链。
JavaScript 中的继承
The text was updated successfully, but these errors were encountered: