1. new关键字后面跟函数 是一个表达式(运算符) 创建对象的运算 整个表达式一定会得到一个对象。
2.new fn()的隐式操作如下:(只要看到new关键字,就可以按照以下3步来分析)
(1) 创建一个空对象 给它添加一个属性 __proto__(注意:这个属性是浏览器后来才设定的 一开始没有这个技术的 再后来控制台显示不可见 隐式可用 ),__proto__就是fn函数的prototype属性对应的对象:系统内置的空对象{}
(2)运行构造函数,让内部的this指向创建的对象(用创建的空对象去调用构造函数)
(3) 整个表达式的结果看函数的返回值:
如果返回值是引用数据 那么就是返回值
如果返回值不是引用数据 那么就是这个运行完毕之后的创建的那个对象(这里需要注意的是当函数没有写return时,也是有返回值的,默认为undefined)
例如:
function fn() {
this.name = "xiaozhang"
return function fm() {
this.name = "xiaoli"
}
}
var f1 = new fn()
console.log(f1.name)
结果:
分析:
1. 先通过new关键字创建了一个空对象 {} ,给它添加一个__proto__属性指向fn的prototype属性
2. new fn()等价于{}.fn(),所以函数中的this指向的是创建的对象
3.但是函数fn的返回值是一个函数(函数也是一个引用数据),所以表达式的结果就是返回值
4.所以f1就等于函数fm
5.所以最终打印的f1.name=fm
3 任何对象都是函数创建出来的 ==> 任何对象都有构造函数
4 new 后面一般跟一个函数 new会创建对象,而且会去调用这个函数
new fn ==> 创建对象 然后调用函数 不传参 ==> new无参
new fn() ==> 创建对象 然后调用函数 并传参 ==> new带参
例如:
function fn(a) {
this.a = a
}
var re = new fn
console.log(re)
结果:
因为fn并没有传入参数,函数只是声明了一个a,没有赋值,因此打印出fn {a:undefined}。
function fn(a) {
this.a = a
}
var re = new fn(200)
console.log(re)
结果:
这种就是传入了参数,函数声明了一个a并给它赋值为200,所以打印fn {a:200}。
5.笔试题
function parent() {
this.a = 1;
this.b = [1,2,this.a];
this.c = {
demo:5
}
this.show = function() {
console.log(this.a,this.b,this.c.demo)
}
this.change = function() {
this.a = this.b.length;
this.c.demo = this.a++;
}
}
var parent = new parent()
parent.change()
parent.show()
结果:
分析:一:看到有new关键字就还是按照之前说的那3步来分析; 1.创建一个空对象 2.函数中的this指向创建的对象 3.看函数的返回值,明显不是引用数据,所以表达式结果就是创建的那个对象。
二:this指向的是创建的对象,所以是在对象中声明赋值了a=1, b=[1,2,1](注意这里是把a的值取出来再赋值到b里面) c={demo:5} 还有一个show方法和一个change方法,也就是show和change对应的那两个函数
三:然后又运行了里面的change函数,给a重新赋值为b数组的长度,值为3;但是注意这 里的a改变了,并不会影响到b数组;然后c.demo又赋值为a++;这里的考点是a++和++a 的区别,a++是先取值再加1,++a是先加1再取值;所以c.demo=3。但是这里执行完之后 a就加了1,所以a=4.
四:最后执行show函数,打印出a,b,c.demo的值分别为4,[1,2,1],3