“this”、构造器+“new”

90 阅读3分钟

这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情

导入

  • 在探讨“this”前先来说说对象中的方法
let user = {
  name: "John",
  age: 30
};

user.sayHi = function() {
  alert("Hello!");
};

user.sayHi(); // Hello!
  • 创建一个函数并指定给对象的user.sayHi属性,这个函数就是方法
这部分方法的代码还可以简写:
let user = { 
name: "John",
  age: 30,
    sayHi() { // 与 "sayHi: function(){...}" 一样
         alert("Hello");
    } 
};
  • 这里思考一个问题,那如果我们想在方法内部访问user的name属性该怎么办? 这时候我们就该谈谈“this”
  • this.name 与 user.name 效果一致,这时候我们就用“this.XXX”即可调用对象中的属性

新的疑问,既然可以用user.XXX那为什么还用“this” ?

let user = {
  name: "John",
  age: 30,

  sayHi() {
alert( user.name ); // 导致错误,如果是this.name不会有错误
  }

};

let admin = user;
user = null; // 重写让其更明显

admin.sayHi(); // TypeError: Cannot read property 'name' of null,this.name就会输出John
  • 很明显,这样可避免拷贝后重写带来的对象改变影响引用的问题
this 的值是在代码运行时计算出来的,它取决于代码上下文。
let user = { name: "John" };
let admin = { name: "Admin" };

function sayHi() {
  alert( this.name );
}

// 在两个对象中使用相同的函数
user.f = sayHi;
admin.f = sayHi;

user.f(); // John(this == user)
admin.f(); // Admin(this == admin)

admin['f'](); // Admin(使用点符号或方括号语法来访问这个方法,都没有关系。)
  • 如果 obj.f() 被调用了,则 this 在 f 函数调用期间是 obj。所以在上面的例子中 this 先是 user,之后是 admin

箭头函数有些特别:它们没有自己的 this。如果我们在这样的函数中引用 thisthis 值取决于外部“正常的”函数。

let user = {
  firstName: "Ilya",
  sayHi() {
    let arrow = () => alert(this.firstName);
    arrow();
  }
};

user.sayHi(); // Ilya

构造函数

  • 我们使用{……}只能创建创建一个对象,但是当我们想创建多个类似的对象这时就需要构造函数

规则:

  1. 它们的命名以大写字母开头。
  2. 它们只能由 "new" 操作符来执行。

使用

function User(name) {
  this.name = name;
  this.isAdmin = false;
  this.sayHi = function() { alert( "My name is: " + this.name ); };\
}

let user = new User("Jack");

alert(user.name); // Jack
alert(user.isAdmin); // false
user.sayHi(); // My name is: Jack

当一个函数被使用 new 操作符执行时,它按照以下步骤:

  1. 一个新的空对象被创建并分配给 this
  2. 函数体执行。通常它会修改 this,为其添加新的属性。
  3. 返回 this 的值。

换句话说,new User(...) 做的就是类似的事情:

function User(name) {
// this = {};(隐式创建)

  // 添加属性到 this
  this.name = name;
  this.isAdmin = false;

// return this;(隐式返回)
}
  • 这里我们就明白构造器的作用了,就是方便重用,减少代码的书写。这里要注意箭头函数没有构造函数
// 创建一个函数并立即使用 new 调用它
let user = new function() {
  this.name = "John";
  this.isAdmin = false;

  // ……用于用户创建的其他代码
  // 也许是复杂的逻辑和语句
  // 局部变量等
};
  • 当我们不想用可重用的普通单个对象就用上面的对象方法即可

省略括号

顺便说一下,如果没有参数,我们可以省略 new 后的括号:

let user = new User; // <-- 没有参数
// 等同于
let user = new User();

这里省略括号不被认为是一种“好风格”,但是规范允许使用该语法。