创建对象
JavaScript对每个创建的对象都会设置一个原型,指向它的原型对象。
当我们用obj.xxx
访问一个对象属性的时候,JavaScript引擎会现在当前对象上查找该属性,如果找不到,就在其原型对象上找,如果还是没有,就会上溯Object.prototype
对象找,如果还没有的话就会返回 undefined
。
- 创建一个
Array
对象:
let arr = [1,2,3,4,5];
它的原型链是:
arr ----> Array.prototype ----> Object.prototype ----> null
Array.prototype
定义了indexOf(),shift()
等方法,所以可以在Array的对象上直接调用这些方法。
- 创建一个函数
function f1() {
return 0;
}
f1()
的原型链:
f1 ---> Function.prototype ----> Object.prototype ----> null
由于Function.protype
定义了call(),apply()
等方法,因此所有函数都可以调用这些方法。如果原型链很长,访问一个对象的属性就会花更多的时间来查找而变得更慢。
构造函数
用构造函数的方法创建一个对象,首先定义一个构造函数:
function Person(name,age) {
this.name = name;
this.age = age;
this.sayName = function() {
console.log('Hi,'+this.name);
}
}
接下来用关键字 new
来调用函数并返回一个对象。
let Nick = new Person('Nick',23);
Nick.sayName();//'Hi,Nick'
写了 new
关键字,它变成一个构造函数,它绑定的 this
指向新创建的对象,并默认返回 this
,也就是说不需要在最后写return this;
。
Nick
的原型链如下:
Nick ---> Person.prototype ---> Object.prototype ---> null
也就是 Nick
的原型指向 Person
原型,如果再创建别的tom,jerry....这些对象的原型都是和 Nick
一样的。
此外,通过new Person()
创建的对象还从原型上获得了一个 constructor
属性,它指向函数 Person
本身。
Nick.construcotot === Person.prototype.constructor;
Person.prototype.construcor === Person;
Object.getPrototypeOf(Nick) === Person.prototype;
有一点需要注意,创建两个新的对象 Tom
和 Jerry
,但是他们俩的 sayName()
函数虽然名称和代码相同,但实际上是两个不同的函数,如果通过 new Person()
创建很多个对象,他们只需要共享一个sayName()
函数就可以了,能节省很多内存。修改代码如下:
function Person(name,age) {
this.name = name;
this.age = age;
}}
Person.prototype.sayName = function() {
console.log('Hi,'+this.name);
}
特别注意
对象的.__proto__ === 其构造函数.prototype
Object.prototype
是所有对象的直接或间接原型- 所有函数都是由
Function
构造的,任意函数.__proto__ === Function.prototype
class继承
ES6引入了 class
关键词, class
的引入目的是让定义类更简单。
如果使用 class
关键字来编写 Person
:
class Person {
constructor(name) {
this.name = name;}
sayName() {
console.log('Hello,' + this.name);
}
}
通过比较可以发现使用 class
包含了构造函数 constructor
和定义在原型对象上的函数 sayName()
(没使用 function
关键字),这样就避免了 Person.prototype.sayName = fucntion(){...}这样的代码。
使用 class
一个巨大的好处就是更方便继承。如果要从 Person
派生一个 otherPerson
,原型继承的中间对象、原型对象的构造函数都不需要考虑了,可以直接通过 extend
来实现。
class otherPerson extends Person{
constructor(name,city) {
super(name); //使用supper调用父类的构造方法
this.city = city;
}
myCity() {
aler (' I am from ' + this.city);
}
}
otherPerson
的定义也是 class
关键字来实现的,而 extends
表明了原型链对象来自 Person
, otherPerson需要 name
city
两个参数,并且通过 super(name)来调用父类的构造函数。并且otherPerson已经自动获得了父类Person的sayName()
方法。
class
与原有的原型继承没有任何区别,只是简化了原型代码。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!