构造函数
- 什么是构造函数?
通过 new关键字调用的函数,一般称其为构造函数.
- 为什么要使用它?
这里先说下类的概念,在ES5之前是没有类的概念的,ES6才新增了 class,它其实是 ES5的语法糖. 由于之前 没有类的概念,所以一些代码会重复的编写.比如两个工具人去吃饭这个方法,没有类概念就需要编写工具人1 去吃饭,工具人2去吃饭;有了类以后可以定义一个公共的类,里面有去吃饭这个方法,任何工具人都可以调 用这个类,当有成千上万次的调用就显得简单多了
通过将一些对象的公共属性方法封装起来,之后创建一个对象就变得极其简单了
- 如何使用它?
ES5中我们可以通过 function Foo(){} 创建一个构造函数,里面可以添加属性和方法,ES6中我们可以通过 class关键字定义一个类.
-
重要点
-
创建了构造函数,内部通过
this添加的方法属性,只能通过实例化的对象来访问.如;
function Foo(name,age){
this.name = name
this.age = age
}
var bar = new Foo('tom',18)
console.log(bar.name) //此处输出为tom
console.log(Foo.name) //此处输出为Foo
由此我们可以看到,当我们创建实例化的对象访问这个时,可以打印出它的名字;而当我们通过构造函 数访问时,打印出来的是构造函数的名字.再看下面例子:
function Foo(name,age){
this.name = name
this.age = age
}
var bar = new Foo('tom',18)
Foo.sex = '男'
console.log(bar.sex) //此处输出为undefined
console.log(Foo.sex) //此处输出为男
为什么上面实例化的对象访问不到sex属性呢?这里我可以这样理解,在构造函数内部通过 this添加的 方法属性是动态的,这个是需要实例化对象才能访问的,也就是创建n多个实例对象,每个对象访问该属 性都是不一样的.而在构造函数身上添加的属性方法,是属于静态的,也就是只能通过构造函数来访问, 你实例对象是访问不到的.
原型对象
这里先说明下,虽然构造函数简单易用,但是它会造成内存浪费的问题.如图:
当我们已经有了一个构造函数了,其中有一个方法,我们创建的bar,abar两个实例对象访问这个方法,内存 中会分配两块内存空间,实例对象对应访问同一个方法.明明是同一个方法,却还要分配两块内存调用,这不 就造成了内存浪费了么.那么怎么解决这个问题呢?就需要用了解下面的原型对象 prototype
- 什么是原型对象?
JavaScript规定,每一个函数都有一个prototype属性,指向另一个对象.prototype本身也是一个对象,这个 对象的所有属性及方法,都被构造函数所拥有.
这里我们就知道了原型对象 prototype 其实就是一个对象,是构造函数的的属性.
我们可以打印看下:
- 原型对象的作用?
我们可以把不变的方法,直接定义到原型对象上,这样所有的实例都可以访问共享的方法,这样不就解决了
构造函数内存浪费的问题了么.
- 如何使用呢?
function Foo(){}
Foo.prototype.move = function(){
console.log("我移动了")
}
var bar = new Foo()
var abar = new Foo()
bar.move()
abar.move()
通过构造函数 .prototype的方法为它添加一个方法,然后创建的两个实例都可以使用了,那么如何验证他 们是同一个内存地址中的方法的呢?我们可以打印看下
结果显示为true,如果不是通过原型对象添加的方法呢?
结果显示为false.
对象原型
既然每一个函数都有 prototype,那么我们实例有没有呢?我们实践打印下
图中我们可以看出,实例对象是没有 prototype属性的,但是它有个一个__proto__,这个就是我们说的对象 原型
- 什么是对象原型?
系统为我们对象身上自动添加的一个 __proto__ 属性,它指向我们构造函数的原型对象 prototype.
只要是对象它就有 __proto__原型
我们可以检验下它是否是指向构造函数的原型对象:
图中结果返回true,由此可以证明.那我们可以这样理解,当我们创建的实例访问方法时,它通过 __proto__ 查找 prototype 属性上的方法,这就是为什么创建的实例可以访问构造函数原型对象上的方法原因.
注意 : 在实际开发中我们是不直接使用实例对象的
constructor
在每个原型对象 prototype 及对象原型 __proto__中都有一个 constructor属性, 该属性指向的时构造函数本身.
也可以利用 constructor手动指向构造函数.
原型链
上面我们在对象原型中说过只要是对象就有 __proto__ 原型.那么,我们的原型对象有没有呢?
我们实际打印看下
我们打印原型对象以后发现,其中也有原型.
我们知道实例对象中的原型指向的是构造函数,那么原型对象中的原型指向的是谁呢?
我们展开打印内容看下,可以看到 constructor 指向的是Object.
为此我们可以验证下原型对象prototype的原型__proto__ 是否九四Object的原型对象prototype
结果显而易见,那么 Object的原型对象 prototype的原型__proto__指向的是谁呢?
结果为空,这里我们可以将它的关系画一张来表示
这一层一层的就是原型链了.
以上是关于自己学习理解整理的内容.有错误的地方肯请各位指出.