1. new关键字后面跟函数 是一个表达式(运算符) 创建对象的运算 整个表达式一定会得到一个对象
2.new fn()的隐式操作如下:(只要看到new关键字,就可以按照以下3步来分析)
1. 创建一个空对象 给它添加一个属性 __proto__(注意:这个属性是浏览器后来才设定的 一开始没有这个技术的
再后来控制台显示不可见 隐式可用 ),__proto__就是fn函数的prototype属性对应的对象:系统内置的空对象{}
2. 运行构造函数,让内部的this指向创建的对象(用创建的空对象去调用构造函数)
3. 整个表达式的结果看函数的返回值:
如果返回值是引用数据 那么就是返回值
如果返回值不是引用数据 那么就是这个运行完毕之后的创建的那个对象
(这里需要注意的是当函数没有写return时,也是有返回值的,默认为undefined)
比如:
结果:
分析步骤:
1. 先通过new关键字创建了一个空对象 {} ,给它添加一个__proto__属性指向fn的prototype属性
2. new fn()等价于{}.fn(),所以函数中的this指向的是创建的对象
3.但是函数fn的返回值是一个函数(函数也是一个引用数据),所以表达式的结果就是返回值
4.所以f1就等于函数fm
5.所以最终打印的f1.name=fm
3. 任何对象都是函数创建出来的 ==> 任何对象都有构造函数
-
new 后面一般跟一个函数 new会创建对象,而且会去调用这个函数
new fn ==> 创建对象 然后调用函数 不传参 ==> new无参 new fn() ==> 创建对象 然后调用函数 并传参 ==> new带参
比如:
结果:
因为fn并没有传入参数,函数只是声明了一个a,没有赋值,因此打印出fn {a:undefined}。
比如:
结果:
这种就是传入了参数,函数声明了一个a并给它赋值为200,所以打印fn {a:200}。
练习题:
结果:
分析:一:看到有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