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 #9

Open
lovelmh13 opened this issue Jan 30, 2020 · 0 comments
Open

如何实现一个 new #9

lovelmh13 opened this issue Jan 30, 2020 · 0 comments

Comments

@lovelmh13
Copy link
Owner

lovelmh13 commented Jan 30, 2020

function myNew(fn, ...arg) {
	var obj = Object.create(fn.prototype);	// 创造一个新对象,与构造函数的原型联系上;
	// Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。 
	var res = fn.apply(obj, arg);	// 改变上下文,把this挂到obj上
	return res instanceof Object ? res:obj;
}

function Bar(name, age) {
	this.name = name;
	this.age = age;
}
Bar.prototype.sayName = function () {
	return this.name;
}
var bar = myNew(Bar, 'lmh', 24);
console.log(bar.name);
console.log(bar.age);
console.log(bar.sayName());


/* -------------------------------- 以前的写法,没区别 -------------------------------- */
function create(Con, ...args) {
	let obj = {};
	obj.__proto__ = Con.prototype;
	let result = Con.apply(obj, args);

	if (result instanceof Object) {
		return result;
	} else {
		return obj;
	}
}

function Test(name, age) {
	this.name = name
		this.age = age
	}
	Test.prototype.sayName = function () {
		console.log(this.name)
	}
	const a = create(Test, 'lmh', 23);
	console.log(a.name) // 'lmh'
	console.log(a.age)  // 23
	a.sayName()         // 'lmh'
}

原理:
要实现一个new, 首先要先了解new都干了些什么

new创建一个构造函数的实例,使其含有构造函数的属性,并且__proto__可以访问到构造函数原型链中的属性

  • 内部创建一个新的空对象
  • 把新对象的__proto__与构造函数的prototype联系上
  • 把新对象this指到构造函数上(用到继承 call apply)成为新的非空对象
  • 判断返回的新对象是简单类型还是复杂类型,复杂类型的话要返回构造函数本身(用过apply指向构造函数的那个对象),简单类型返回新的对象(__proto__与构造函数的prototype联系的对象,没有把this指向构造函数的那个对象)
    (因为new 的时候就是这个么返回的,实例本来就是希望继承构造函数的属性,含有构造函数的原型的,并不希望得到的是构造函数的返回值)

-----------------------------------2020.8.16更新-----------------------------------
看了mdn的解释,感觉更清除一些

转自mdn:

new 关键字会进行如下的操作:
创建一个空的简单JavaScript对象(即{});
链接该对象(即设置该对象的构造函数)到另一个对象 ;
将步骤1新创建的对象作为this的上下文 ;
如果该函数没有返回对象,则返回this。

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

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

1 participant