1

图片

2021年是全新的一年,是一个积极性向上富有活力的一年,让我们起航开启新的征程,一切的一切都重新开始,今天讲一讲关于new的事情,大家一起加油!

一、定义

new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。

二、语法

new constructor[([arguments])]

constructor一个指定对象实例的类型的类或函数。
arguments一个用于被constructor调用的参数列表。

三、例子

例一、创建一个自定义类

/**
 * 关键字function创建类
 */
function YearFunction(){
}
let yearFn = new YearFunction();
/**
 * 关键字class创建类
 */
class YearClass{
}
let yearCs = new YearClass();
console.log(yearFn);
console.log(yearCs);

图片

总结
有两种方式创建类,一种用关键字function,另一种用关键字classclass可以作为function创建类的一种语法糖。

例二、创建具有属性的自定义类

function YearFunction(year, month, day){
  this.year = year;
  this.month = month;
  this.day = day;
}
let yearFn = new YearFunction(2021, 1, 1);
class YearClass{
  constructor(year, month, day){
    this.year = year;
    this.month = month;
    this.day = day;
  }
}
let yearCs = new YearClass(2021, 1, 1);
console.log(yearFn);
console.log(yearCs);

图片

总结
在定义属性时,function直接写在方法体内部,class是写在constructor构造函数内容。

例三、创建具有函数的自定义类

function YearFunction(year, month, day){
  this.year = year;
  this.month = month;
  this.day = day;
}
YearFunction.prototype.getYear = function getYear(){
  return this.year;
}
let yearFn = new YearFunction(2021, 1, 1);
class YearClass{
  constructor(year, month, day){
    this.year = year;
    this.month = month;
    this.day = day;
  }
  getYear(){
    return this.year;
  }
}
let yearCs = new YearClass(2021, 1, 1);
console.log(yearFn);
console.log(yearCs);

图片

总结
在定义方法时,function需要在prototype属性上显示声明函数,class在类的内部定义。细心的你,function声明的方法多了一个prototype,这是class创建类比function的优化的地方。

例四、实例与类的关系

class YearClass{
  constructor(year, month, day){
    this.year = year;
    this.month = month;
    this.day = day;
  }
}
let yearCs = new YearClass(2021, 1, 1);
console.log(yearCs instanceof YearClass);  // true
console.log(yearCs instanceof Object);  // true
console.log(yearCs.constructor === YearClass);  // true
console.log(yearCs.constructor === Object);  // false
console.log(yearCs.__proto__ === YearClass.prototype);  // true 不推荐
console.log(Object.getPrototypeOf(yearCs) === YearClass.prototype);  // true 推荐

图片

总结
对象的constructor指向类,对象的__proto__指向类的prototype

例五、不声明参数

class YearClass{
  constructor(year = 2000, month = 1, day = 1){
    this.year = year;
    this.month = month;
    this.day = day;
  }
}
let yearCsUnparams = new YearClass;
let yearCsparams = new YearClass(2021, 1, 1);
let yearCsDefparams = new YearClass();
console.log(yearCsUnparams);
console.log(yearCsparams);
console.log(yearCsDefparams);

图片总结
创建类时,可以显示声明参数,还可以忽略参数部分,这时创建对象时使用默认参数。

例六、模拟new的实现

function newFactory(csName){
  var obj = new Object();
  var CsName = [].shift.apply(arguments);
  obj.__proto__ = CsName.prototype;
  var result = CsName.apply(obj, arguments);
  return typeof result === 'object'?result:obj;
}
function YearFunction(year, month, day){
  this.year = year;
  this.month = month;
  this.day = day;
}
console.log(newFactory(YearFunction, 2021, 1, 1));
console.log(new YearFunction(2021, 1, 1));

图片

总结
当代码new Year(...)执行时,会发生以下事情:
1、一个继承自 Year.prototype 的新对象被创建。
2、使用指定的参数调用构造函数Year,并将this绑定到新创建的对象。new Year等同于new Year(),也就是没有指定参数列表,Year不带任何参数调用的情况。
3、由构造函数返回的对象就是 new 表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤1创建的对象(一般情况下,构造函数不返回值,但是用户可以选择主动返回对象,来覆盖正常的对象创建步骤)。

图片

喜欢可以关注微信公众号“前端咖”


前端咖
7 声望0 粉丝