一、new的执行
首先来说一下在js中创建对象的三种方法。
- 对象字面量
- 构造函数
- 自定义构造函数
var obj = {} // 对象字面量
var obj2 =new Object();// 构造函数
function Car(color){//自定义构造函数
this.name='BMW'
this.hieght=1400
this.lang=4900
this.weight=1000
this.color=color
}
let car =new Car('green')
let car2=new Car('pink')// 可以批量生产对象
console.log(Car('red'))// 返回undefined
在构造函数和自定义构造函数中都使用了new来创建对象,并且在不 使用new直接调用时返回了一个undefined。由此我们能看出创建对象主要是因为使用了new而不是构造函数。简单的说new的过程就是:
- 1.创建this空对象
- 2.执行构造函数中的逻辑
- 3.返回this对象
二、包装类
原始类型不能具有属性和方法, 属性和方法是对象独有的
var num=123
num.a='hello'
console.log(num.a);// undefined
相信看了这段代码以及我的这个小标题你们不由得生出了一个疑问,为什么说原始类型不能具有属性和方法但是在输出时却不报错,而是输出了undefined。
var num=new Number(123);// 除null和undefined外都有构造函数
num.a='hello'
console.log(num.a);// hello
是的,在v8引擎中给number,string,Boolean等都内置了构造函数。不仅是复杂数据类型,简单数据类型也有。所以在v8引擎中
var num=123
var num=new Number(123);
这两行代码是等同的。但是为什么在输出时却一个能输出'hello'一个输出了undefined。那是因为在他们不全等同,var num=123
相比var num=new Number(123);
后面还有着别的步骤
当v8引擎识别到
var num=123
他首先会按var num=new Number(123);
那样去执行,因为都返回了一个对象能够添加属性值,这就是用了new来调用number的构造函数,但是在你往num身上添加属性时,v8引擎会意识到 “原始属性不能具有属性和方法” 会立刻将你添加的属性删除,因此var num=123
num.a='hello'
在v8引擎中整个的执行步骤是这样的。
var num=new Number(123)
num.a='hello'
delete num.a
当执行num.a='hello'
。首先是会向num添加一个a属性,然后再赋值为'hello',接着被v8引擎自动delete
掉,然后当我们运行console.log(num.a);
时,是先直接往num添加了一个新的a属性然后值为undefined,并不是前面那个num.a='hello'
,这段代码添加的a属性已经被删除了。
而这个过程就是包装类
var num=new Number(123)
num.a='hello'
delete num.a
面试考点
let str='abcd'
console.log(str.length)// 输出4
关于包装类有一个面试的考点。原始类型不能具有属性和方法。那为什么str有一个length属性。
var arr=[1,2,3,4]
arr.length=2
console.log(arr);// 输出[1,2]
let str='abcd'
str.length=2
console.log(str)// 输出abcd
这里我们能发现,当我们修改length时,arr本身会受到影响,而str不会受到影响。其实上面那个问题的答案就是str身上其实根本没有length属性,str.length=2
在String的包装类中依然是在添加后被直接删除了,那我们为什么又能访问到str的长度呢。
其实是因为我们访问的这个length并不是str的属性,而是String这个构造函数这个包装类的length属性。
fucntion String(str){
this.length=0
}