Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

new操作符的实现原理 #10

Open
lhlGitHub opened this issue Jan 5, 2022 · 3 comments
Open

new操作符的实现原理 #10

lhlGitHub opened this issue Jan 5, 2022 · 3 comments

Comments

@lhlGitHub
Copy link
Owner

No description provided.

@longweixia
Copy link

1-1.使用场景

当需要创建多个对象的时候,如果循环会「重复创建」很多变量,占用内存。

如果用new生成,那么里面重复的属性是在「原型」上,就不用占用内存。

1-2.意义

节省代码,属于语法糖,可以拥有使用构造函数里面的所有「属性和方法」,并且还可以「拓展」。

1-3.实现步骤

  • 传入参数为:构造函数和函数参数
  • 创建1个空对象
  • 使空对象的__proto__指向构造函数的原型(prototype)
  • 将this绑定到空对象上,执行构造函数
  • 判断构造函数的返回值,如果是对象,直接返回这个值。如果不是,就返回开始创建的对象

1-4.代码实现

新建构造函数--用来new的函数

// 构造函数是一种特殊的方法:用来在创建对象时为对象成员变量赋初始值
function Dog(name){
  // 这里的this指向window,所以下面才需要重新将this指向自身,这样才能将属性挂载成功
  this.name = name
  this.say = function() {
    console.log("my name is" + this.name);
  }
}

手写new函数

function _new(fn,...arg){
  const obj = {};
  // 将构造函数的原型挂载到新对象上
  Object.setPrototypeOf(obj, fn.prototype)
  // 将this指向新对象,执行构造函数
  let result = fn.apply(obj, arg);
  return result instanceof Object ? result : obj
}

验证

var dog = _new(Dog, "caigou")
dog.say();// my name is caigou

@13168335674
Copy link

function _new(target, ...args) {
    const obj = Object.create(target.prototype);
    const ret = target.apply(obj, args);
    return typeof ret === 'object' ? ret : obj;
}

@zhanglongLee
Copy link
Collaborator

new操作符的实现原理

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

举个例子

// Otaku 御宅族,简称宅
function Otaku(name, age) {
    this.name = name
    this.age = age
}
// 重量
Otaku.prototype.weight = 80
Otaku.prototype.sayHi = function () {
    console.log(`I am ${this.name},age is ${this.age}.`);
}
let person = new Otaku("张三", 12)
console.log(person.name);//张三
console.log(person.age);//12
console.log(person.weight);//80
person.sayHi();// I am 张三,age is 12.

从这个例子中,我们可以看到person实例可以:

  1. 访问到 Otaku 构造函数的属性;
  2. 访问到 Otaku.prototype 中的属性或方法;

注意:加入构造函数有返回值,并且返回值是对象,则new操作符会返回该对象

// Otaku 御宅族,简称宅
function Otaku(name, age) {
    this.name = name
    this.age = age
    return{
        name:"哈哈",
        age:22
    }
}
// 重量
Otaku.prototype.weight = 80
Otaku.prototype.sayHi = function () {
    console.log(`I am ${this.name},age is ${this.age}.`);
}
let person = new Otaku("张三", 12)
console.log(person.name);//哈哈
console.log(person.age);//22
console.log(person.weight);//undefined
person.sayHi();//报错

实现一个new函数:

function objectFactory() {
    let obj = new Object()
    Constructor = Array.prototype.shift.call(arguments)// 将构造函数取出,arguments剩余的数据为传入的参数
    // 将原型指向obj
    obj.__proto__ = Constructor.prototype
    let result = Constructor.apply(obj, arguments)
    // 如果构造函数的返回值不为对象,则返回obj。否则返回该对象result
    return Object.prototype.toString.apply(result).includes("Object") ? result : obj
}

测试

// Otaku 御宅族,简称宅
function Otaku(name, age) {
    this.name = name
    this.age = age
}
// 重量
Otaku.prototype.weight = 80
Otaku.prototype.sayHi = function () {
    console.log(`I am ${this.name},age is ${this.age}.`);
}
// let person = new Otaku("张三", 12)
let person = objectFactory(Otaku, "张三", 12)
console.log(person.name);//张三
console.log(person.age);//12
console.log(person.weight);//80
person.sayHi();//I am 张三,age is 12.

参考链接

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants