-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
第 14 题:情人节福利题,如何实现一个 new #12
Comments
这样写是不是简单点啊 function _new(fn, ...arg) {
const obj = Object.create(fn.prototype);
const ret = fn.apply(obj, arg);
return ret instanceof Object ? ret : obj;
} |
@zwmmm 你是对的,我写的有点问题 |
function _new(fn, ...arg) { |
function _new(){
const obj = {}
const Constructor = Array.prototype.shift.call(arguments)
obj.__proto__ = Constructor.prototype
const result = Constructor.apply(obj, arguments)
return typeof result === 'object' ? result : obj
} |
/**
*
*
* @param {Function} fn
*/
function _new(fn, ...args) {
const obj = {};
Object.setPrototypeOf(obj, fn.prototype);
const result = fn.apply(obj, args);
// 根据规范,返回 null 和 undefined 不处理,依然返回obj
return result instanceof Object ? result : obj;
} |
之前写过一篇模拟实现 我的这篇文章主要提出了对返回值是函数和对象的处理,还有对
|
我也贴一个 |
写的真好 |
这样ret不是一直都是undefined吗?res instanceof Object就一直是false啊 |
当然不是,这里判断构造函数执行的返回类型,如果构造函数执行结果返回的是个对象不就是true了 |
构造函数是默认返回对象的(但是这个是没有返回值的)。但是你也可以自己return一个对象。 |
先理清楚 new 关键字调用函数都的具体过程,那么写出来就很清楚了
|
function _new(fn , ...args){ |
function _new(fn, ...args){ |
两处错误 |
关于为什么最后要判断 return ret instanceof Object ? ret : obj function _new(fn, ...arg) {
const obj = Object.create(fn.prototype);
const ret = fn.apply(obj, arg);
//return ret instanceof Object ? ret : obj;
return obj;
}
function A(d) {
this.d = d;
return {
a: 6
};
}
console.log(new A(123)); //{a: 6}
console.log(_new(A, 123)); //A {d: 123} |
内部创建对象的时候也不能使用new来吧.. |
new运算符都做了哪些操作呢? 下面就写一个实现new功能的函数: function mynew () {
// 1、创建一个新对象
const obj = Object.create({}); // 也可以写成 const obj = {}
// 2、将this指向该对象
let Fn = [].shift.call(arguments); // 把构造函数分离出来
let returnObj = Fn.apply(obj, arguments); // 通过apply将this指向由Fn变为obj
// 3、将新对象的原型指向构造函数的原型
obj.__proto__ = Fn.prototype
// 4、返回对象(如果构造函数有返回对象,那么就返回构造函数的对象,如果没有就返回新对象)
return Object.prototype.toString.call(returnObj) == '[object Object]' ? returnObj : obj;
} |
// 首先创建一个空的对象,空对象的__proto__属性指向构造函数的原型对象 |
|
function New (func) {
var res = {}
if (func.prototype !== null) {
res.__protp__ = func.prototype
}
var ret = func.apply(res, Array.prototype.slice.call(arguments, 1))
if ((typeof ret === 'object' || typeof ret === 'function') && ret !== null) {
return ret
}
return res
} |
function create(){ |
應另外確認null,new關鍵字針對null是處理成回傳this function _new(fn, ...args) {
const object = Object.create(fn.prototype)
const result = fn.call(object, ...args)
return typeof result === 'object' && result !== null ? result : object
} |
call和apply在绑定this时会立即执行,bind才是单纯绑定this,所以你得
|
建议去mdn看下__proto__,这个属性性能极差,而且已经废弃(不安全)。应该在构造函数的原型上做手脚,而不是利用实例的__proto__做手脚。实例和构造函数还是要区分的。 |
|
这里需要返回值,判断是不是对象,是的话返回该对象,不是的话返回obj |
const result = fn.apply(obj, ...arg);的apply应该改为call吧,或者把...去掉 |
class Foo {
constructor() {
this.foo = 42;
}
}
function _new(fn, ...arg) {
const obj = Object.create(fn.prototype);
const ret = fn.apply(obj, arg);
return ret instanceof Object ? ret : obj;
}
new Foo(); //{foo: 42}
_new(Foo); //TypeError: Class constructor Foo cannot be invoked without 'new' 这个_new并不等价new |
var obj = new A() |
|
详细可参考mdn关于new运算符第四条定义 |
new 关键点new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。new 关键字会进行如下的操作:
function Dog(name) {
this.name = name
}
Dog.prototype.sayHi = function() {
console.log('hello its me')
}
Dog.prototype.sayName = function() {
console.log('my name is ' + this.name)
} 方法一 // 实现一个new
// 1,创建一个新的对象obj
// 2,将obj的__proto__指向Dog.prototype实现继承
// 3,执行构造函数,传递参数,改变this指向
// 方法一
function _new() {
let args = arguments
let constructor = Array.prototype.shift.call(args)
const obj = new Object()
Object.setPrototypeOf(obj, constructor.prototype)// 和下面一句是同样的效果
// obj.__proto__ = constructor.prototype
constructor.call(obj, ...args)
return obj
} 方法二 function _new2(fn, ...arg) {
// 这一句话只是构造了一个对象,这个对象的__proto__=== fn.prototype
var obj = Object.create(fn.prototype)
// 并没有给这个对象赋值,将fn的this对象设置为obj
// call 是列表, apply是数组
const ret = fn.call(obj, ...arg)
// 为啥这里需要判断一下ret,根据new的定义,如果构造函数没有返回一个对象,那么返回this对象,this当前就是obj
return ret instanceof Object ? ret : obj
} |
还可以这么写
|
fn.apply(obj, ...arg);应该用call或者arg |
请问大家,有用自己写的这个 _new 方法试过 _new(Number,123)或_new(String,"abc") 吗? |
改进一下
create(Number,123) |
|
/**
|
|
JavaScript中的new操作符面试题根据
以上4条是 var self;
function Person(name) {
console.log(this);
self = this;
this.name = name;
}
let p = new Person("张三");
console.log(p);
console.log(self === p); // true 构造函数中的this 绑定在了p这个对象上
console.log(p.__proto__ === Person.prototype); // 对象p的原型属性指向构造函数的原型,这样也就保证了实例能够访问在构造函数原型中定义的属性和方法。 然后在构造函数添加原型方法 function Persion(name){
this.name = name
}
console.log(Persion.prototype)
Persion.prototype.sayHello = function(){
console.log(this) // 指向构造出的对象
console.log(this.name) // 小明
}
let xiaoMing = new Persion('小明')
xiaoMing.sayHello() 经过上文的简单案例我们可以得知,
构造函数说白了也是一个函数,那是函数就可以有返回值 function Person(name) {
this.name = name;
// return 1; // 返回内部新创建的对象
// return "1"; // 返回内部新创建的对象
// return null; // 返回内部新创建的对象
// return undefined; // 返回内部新创建的对象
// return {}; // {} // 直接返回
return function () {}; // 直接返回
return [1]; // [1] // 直接返回
}
let p = new Person("李四");
console.log(p); 有了给构造函数返回一个值得想法,那就通过不同的
小结也就是说,构造函数一般不需要
手写一个自己的myNew如果自己实现一个new 的话,首先要满足它的几点效果
测试成果
|
|
实例代码: function Person(name){
this.name = name;
}
Person.prototype.getName = function() {
return this.name;
}
var p1 = new Person('Dan');
console.log(p1); // Person {name: "Dan"}
console.log(p1.__proto__ === Person.prototype); // true new 操作符实现了如下的功能:
前面提到了隐式的返回,如果是显式返回呢? 构造函数如果返回基本类型,则还是会返回原来的 this (新对象)。如果返回的是引用类型,则返回该返回值。(可以自己在上面例子加上代码验证一下) new 操作符的模拟实现function createNew(func, ...args) {
let obj = {};
// 将空对象指向构造函数的原型链
Object.setPrototypeOf(obj, func.prototype);
// obj 绑定到构造函数上,便可以访问构造函数中的属性
let result = func.apply(obj, args);
// 如果返回的 result 是一个对象则返回该对象,new 方法失效,否则返回 obj
return result instanceof Object ? result : obj;
}
写个测试用例: function Test(name, age) {
this.name = name;
this.age = age;
}
let test = createNew(Test, 'Dan', 20);
console.log(test.name); // Dan
console.log(test.age); // 20 Reference |
function _new(fn, ...arg) {
const obj = Object.create(fn.prototype);
const ret = fn.apply(obj, arg);
return ret instanceof Object ? ret : obj;
}
_new(Number, 1).toFixed(2) // Uncaught TypeError: Number.prototype.toFixed requires that 'this' be a Number 这个_new出来的对象调用原型上的方法会报错? |
默写高赞... function _new (fn , ...arg) {
let obj = Object.create(fn.prototype);
let ret = fn.apply(obj, arg);
// 构造函数本就可以返回一个类对象...
// 手动返回基础类型时 or 正常不return时 才返回this
//
// 但是fn不是构造函数... 就是正常执行下.. 为了和正常的构造函数保持一致所以修正一下
return ret instanceof Object ? ret : obj;
}
|
new 都做了什么? function _new(Func, ...args){
let obj = {}
obj.__proto__ = Func.prototype
let result = Func.call(obj, ...args)
return (result!== null && /^(object)|(function)$/.test(typeof result)) ? result : obj
} 第二种实现: function _new(Func, ...args){
let obj = Object.create(Func.prototype)
let result = Func.call(obj, ...args)
return (result!== null && /^(object)|(function)$/.test(typeof result)) ? result : obj
} |
// 实现一个new
// 1. 创建一个空对象,并指向构造函数的原型
// 2. 将空对象指向构造函数的this, 用构造函数内部方法修改空对象
// 3. 如果构造函数返回一个非基本类型的值,则返回这个值,否则返回空对象
function Person(name, age) {
this.name = name;
this.age = age;
}
function _new(fn, ...args) {
const obj = Object.create(fn.prototype);
const result = fn.apply(obj, args);
return result instanceof Object ? result : obj;
}
console.log(_new(Person, "xuzhen", "18")); |
@Hiker9527
|
|
这个题的题目描述是啥... |
function myClass(age,name) { const fn = (cla, ...params) => { let useIt = fn(myClass,24,'wbb') |
鉴于十三题可以说的东西很多,就先看了十四题,作为一个单身狗,new的对象都是一个小狗啊
The text was updated successfully, but these errors were encountered: