JS:new 命令

1、基本用法

new命令的作用,就是执行构造函数,返回一个实例对象。

function Vehicle () {
  this.price = 1000;
}

// new命令执行时,构造函数内部的this,代表了新生成的实例对象
let v = new Vehicle();
console.log(v.price)         // 1000

// 未使用new命令时,构造函数就变成了普通函数,并不会生成实例对象。
// this这时代表全局对象,如果是浏览器环境,this指向window。
let v2 = Vehicle();
console.log(v2)             // undefined
console.log(price)          // 1000
console.log(window.price)   // 1000

2、new 原理

使用new命令时,它后面的函数依次执行下面的步骤。

  1. 创建一个空对象,作为将要返回的对象实例。
  2. 将这个空对象的原型,指向构造函数的prototype属性。
  3. 将这个空对象赋值给函数内部的this关键字。
  4. 开始执行构造函数内部的代码。

注意点:

  • 如果构造函数内部有return语句,且返回值是个对象,new命令会返回该对象;
    否则返回this对象。
// return 的返回值 是对象,new命令返回该对象
function Person (name) {
  this.name = name;
  return {
    name: '李四'
  }
}
let p = new Person('张三');
console.log(p) // Person { name: '李四' }
// return 的返回值 不是对象,new命令返回this对象
function Person (name) {
  this.name = name;
  return '28'
}
let p = new Person('张三');
console.log(p) // Person { name: '张三' }
  • 对普通函数(内部没有this关键字的函数)使用new命令,会返回一个空对象。
function f () {
  return 'Hello world!'
}
let result = new f();
console.log(result) // f {}

3、手写new

function _new(constructor, ...args) {
  // 创建一个空对象,继承构造函数的 prototype 属性
  let context = Object.create(constructor.prototype);
  // 执行构造函数
  let result = constructor.apply(context, args);
  // 如果返回结果是对象,就直接返回,否则返回 context 对象
  return (typeof result === 'object' && result != null) ? result : context;
}

验证:

function Vehicle () {
  this.price = 1000;
}

let v = new Vehicle();
let v2 = _new(Vehicle);
console.log(v)  // Vehicle { price: 1000 }
console.log(v2) // Vehicle { price: 1000 }

4、为了保证构造函数必须与new命令一起使用,两种解决办法

方式一:构造函数内部使用严格模式

一旦忘了使用new命令,直接调用构造函数就会报错。此时this不能指向全局对象,默认等于undefined,导致不加new调用会报错

function Fubar(foo, bar){
  'use strict';
  this._foo = foo;
  this._bar = bar;
}

Fubar() // TypeError: Cannot set properties of undefined (setting '_foo')

方式二:构造函数内部判断是否使用new命令,如果发现没有使用,则直接返回一个实例对象。

  • 可以使用 instanceof 运算符,判断一个对象是否为指定的构造函数的实例。
  • 也可以使用new.target属性。如果当前函数是new命令调用,new.target指向当前函数,否则为undefined。
function Fubar(foo, bar) {
  if (!(this instanceof Fubar)) {
  // if (new.target === undefined) {
    return new Fubar(foo, bar);
  }

  this._foo = foo;
  this._bar = bar;
}

console.log(Fubar(1, 2)._foo)  // 1
console.log((new Fubar(1, 2))._foo)  // 1

5、 题目

填写"TO DO"处的内容让下面代码支持 a.name = "name1"; b.name = "name2";

function Obj(name){
// TO DO
}
Obj./* TO DO */ = "name2";
var a = Obj("name1");
var b = new Obj;

 参考答案:

function Obj(name){
  if (new.target === undefined) {
    this.name = name;
    return this;
  }
}
Obj.prototype.name = "name2";

var a = Obj("name1");
var b = new Obj;
console.log('a', a.name); // a name1
console.log('b', b.name); // b name2

The end.

参考连接:

实例对象与 new 命令 - JavaScript 教程 - 网道

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值