我们在使用函数的过程中,大多数都会使用构造函数,如: new Array(),
出现构造函数的场景
看下面的代码,我们在一个这样的场景下:想创建多个相同的用户,我们可能会使用下面的代码:
function createUser(name, age, sex){ return { name, age, sex, sayHello(){ console.log(`my name is ${this.name}, my sex is ${this.sex} and i am ${this.age}`) } } } var u1 = createUser('twinkle', '18', '男'); u1.sayHello(); var u2 = createUser('twinkle', '18', '男'); u2.sayHello(); console.log(u1 === u2);
在上面的代码中,我们可以创建多个对象,使用函数的方式来创建的对象。(但是这两个对象是不一样的,每一次都创建一个新的对象)可以方便许多,除了上面的方法外,还有一种构造函数的方式来创建对象。
构造函数
语法:
new 函数名(参数1,参数2,……)
改造代码:
function User(name, age, sex){ this.name = name; this.age = age; this.sex = sex; this.sayHello = function(){ console.log(`my name is ${this.name}, my sex is ${this.sex} and i am ${this.age}`) } } var u1 = new User('twinkle', '18', '男'); u1.sayHello(); var u2 = new User('twinkle', '18', '男'); u2.sayHello(); console.log(u1 === u2);
注意事项
- 构造函数的本质也是函数,就是调用的方式不同。
- 构造函数里面会默认自动定义一个this 对象,并且会自动返回当前的this,如果手动返回一个原始类型的数据,不会返回,如果返回的是一个对象,会替换原来的this对象。
- 在js中的内置对象中,全部的对象都是用构造函数 new来创建的。那些简写,是js给出的字面量的创建方式,也就是语法糖;
new.target
用于判断对象的调用方式是否使用构造函数的方式来调用,如果不是构造函数调用,该表达式返回undefined, 否则返回正常的构造函数。
function U(){ if(new.target !== U){ console.error('请使用new的方式来创建函数') } } U(); new U();
构造函数与函数的区别
- 命名方式,其实这一点不能说为区别,只是在业界中形成一定的规范,普通函数是小驼峰的名命方式,而构造函数是大驼峰的名命方式;
- 在重温js——函数表达式和this_twinkle的博客-CSDN博客中,我们知道普通函数的this指向是指向全局对象的,而构造函数内部的this指向当前对象的实例.
- 使用的方式不同,普通函数直接调用,构造函数必须使用new 来调用,通过 new.target 来判断调用的方式是不是构造函数。
函数的本质
函数的本质就是对象。
function sum (a,b){ return a + b; } var sum1 = new Function('a','b', 'return a + b'); sum(1,3); sum1(1,3)
所有的函数都是 new Function 来创建的。
包装类
js 为了增强原始类型的数据,为string, boolean, number 分别创建了一个构造函数。 String, Boolean, Number。在js中,可以认为类就是一个构造函数。
如果语法上,将原始类型当作对象来使用时(一般在使用属性时),JS会自动在该位置利用对应的构造函数,创建对象来访问原始类型的属性。
// a.toFixed(2)等同于下面的代码 (new Number(a)).toFixed(2);
上图的两个变量,严格是不相等的,两个不一样的对象,对象比的是引用地址,这两个变量肯定是不同的。
成员属性(方法),实例属性(方法), 表示该属性通过构造函数的实例来调用(需要通过new 的方式来调用)。
静态属性(方法),类属性(方法),表示该属性是通过构造函数本身来调用(不用new的方式来调用)