深入解析JavaScript构造函数与原型链
function foo () {
console.log('被实例化了')foo. a = function () {console.log (1)}; this. a = function () {console.log (2)}; a = function () {console.log (3)}; var a = function () {console.log (4)}; } foo. prototype. a = function () {console.log (5)}; foo. a = function () {console.log (6)}; foo. a (); var obj = new foo (); obj. a (); foo. a ();
函数内部分析:
1.在函数内部将foo.a赋值为打印为1的函数
2.this.a相当于把foo这个构造函数的实例对象的a函数赋值为打印为2的函数
3.将一个未声明的a赋值为打印3的函数,相当于设置的全局变量a为打印3的函数
4.var a 赋值为4,相当于在这个函数作用域里面为打印为4的名为a的函数
5.foo.prototype.a 赋值为 5,相当于原型链上改变,如果自身没有a函数才会往上走
5.foo.a又被重新赋值为打印为6的函数
结果:
所以:
1.foo.a() 打印为 6
2.var obj = new foo() ===> 打印为 2
因为obj是foo的实例对象,实例化时,会将函数的this指向实例对象
3.重新调用foo.a。打印为1
构造函数被实例化时,构造函数内部的代码会执行,包括函数定义和函数调用。构造函数内部定义的函数不会自动执行,需要显式调用才会执行。因此 foo.a又会重新赋值为打印1
PS:
如果需要打印为 5就
obj._proto_a() //输出5
或者设置一个实例对象obj身上不存在的属性打印为5
foo.protptype.b = function(){ console.log('实例对象上找不到就往原型链找,5') }
obj.b()
ps:构造函数继承
如果foo(){
function c () {
console.log('构造函数里面的局部函数')
}
function a () {
console.log('构造函数里面的继承函数')
}
this. a = a
}
let obj = new foo()
此时 obj.c () 调用会报错
除非
foo.prototype.c = c
或者
this.c = c
总结:在构造函数内部定义的函数,如果不通过
this
或原型显式地赋值给实例,实例将无法直接访问该函数。