第 14 题:情人节福利题,如何实现一个 new
鉴于十三题可以说的东西很多,就先看了十四题,作为一个单身狗,new 的对象都是一个小狗啊
// 实现一个new
var Dog = function(name) {
this.name = name
}
Dog.prototype.bark = function() {
console.log('wangwang')
}
Dog.prototype.sayName = function() {
console.log('my name is ' + this.name)
}
let sanmao = new Dog('三毛')
sanmao.sayName()
sanmao.bark()
// new 的作用
// 创建一个新对象obj
// 把obj的__proto__指向Dog.prototype 实现继承
// 执行构造函数,传递参数,改变this指向 Dog.call(obj, ...args)
// 最后把obj赋值给sanmao
var _new = function() {
let constructor = Array.prototype.shift.call(arguments)
let args = arguments
const obj = new Object()
obj.__proto__ = constructor.prototype
constructor.call(obj, ...args)
return obj
}
var simao = _new(Dog, 'simao')
simao.bark()
simao.sayName()
console.log(simao instanceof Dog) // true
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(52)
构造函数是默认返回对象的(但是这个是没有返回值的)。但是你也可以自己return一个对象。
先理清楚 new 关键字调用函数都的具体过程,那么写出来就很清楚了
function _new(fn , ...args){
const obj={}
const Constructor = fn
obj.proto = Constructor.prototype
const result = Constructor.call(obj , ...args)
return typeof result === "object" ? result : obj
}
function _new(fn, ...args){
let obj = {}
Object.setPrototypeOf(obj,fn.prototype)
let result = fn.apply(obj,args)
return result instanceof Object ? result : obj
}
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/proto
两处错误
关于为什么最后要判断 return ret instanceof Object ? ret : obj
instanceof Object 来判断是否是对象,包含Array,Object,Function、RegExp、Date
构造函数是可以自己指定返回一个对象的
内部创建对象的时候也不能使用new来吧..
new运算符都做了哪些操作呢?
1、创建了一个新对象(是Object类型的数据)
2、将this指向新对象
3、将创建的对象的原型指向构造函数的原型
4、返回一个对象(如果构造函数本身有返回值且是对象类型,就返回本身的返回值,如果没有才返回新对象)
下面就写一个实现new功能的函数:
// 首先创建一个空的对象,空对象的__proto__属性指向构造函数的原型对象
// 把上面创建的空对象赋值构造函数内部的this,用构造函数内部的方法修改空对象
// 如果构造函数返回一个非基本类型的值,则返回这个值,否则上面创建的对象
function create(){
var obj = new Object();
var src = Array.prototype.shift.call(arguments);
if (src == null) {
return obj;
}
obj._proto = src.prototype;
obj.call(src, ...arguments);
return obj;
}
應另外確認null,new關鍵字針對null是處理成回傳this
call和apply在绑定this时会立即执行,bind才是单纯绑定this,所以你得
建议去mdn看下__proto__,这个属性性能极差,而且已经废弃(不安全)。应该在构造函数的原型上做手脚,而不是利用实例的__proto__做手脚。实例和构造函数还是要区分的。
这里需要返回值,判断是不是对象,是的话返回该对象,不是的话返回obj
const result = fn.apply(obj, ...arg);的apply应该改为call吧,或者把...去掉
这个_new并不等价new
var obj = new A()
new 操作:
var obj = {} obj.__proto__ = A.prototype A.call(obj,arguments)
详细可参考mdn关于new运算符第四条定义
new 关键点
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。new 关键字会进行如下的操作:
创建一个空的简单JavaScript对象(即{});
链接该对象(即设置该对象的构造函数)到另一个对象 ;
将步骤1新创建的对象作为this的上下文 ;
如果该函数没有返回对象,则返回this。 【很关键】
方法一
方法二
还可以这么写
fn.apply(obj, ...arg);应该用call或者arg
请问大家,有用自己写的这个 _new 方法试过 _new(Number,123)或_new(String,"abc") 吗?
改进一下
create(Number,123)
create(String,'abc')
以上情况也支持了
/**
* 实现思想
* 1.首先创建一个对象
* 2.取到arguments的第一个参数也就是传进来的即将被实例化的函数赋值给Con
* 3.将Con.prototyp绑定到当前创建的obj的__proto__ 因为要访问构造函数里原型的属性
* 4.通过apply改变构造函数内部的指向
* 5.最后判断一下构造函数的返还参数 是否是对象
* */
JavaScript中的new操作符
面试题
根据
new操作符
相关的知识点一般会 延伸出以下的面试题 ,面试官你是否有很多问号mdn关于new运算符关键字的描述
以上4条是
MDN
上关于new 操作符(或者说关键字)的面试,简单的来体验下利用构造函数来new
一个对象然后在构造函数添加原型方法
经过上文的简单案例我们可以得知,
new
一个构造函数得到一个对象,它的原型属性(也就是__ proto __)与该构造函数的原型是全等new
通过构造函数Persion
创建出来的实例可以访问到构造函数中的属性,就行这样言简意赅:new出来的实例对象通过原型链和构造函数联系起来
构造函数说白了也是一个函数,那是函数就可以有返回值
有了给构造函数返回一个值得想法,那就通过不同的
数据类型
进行测试得出结论小结
也就是说,构造函数一般不需要
return
手写一个自己的myNew
如果自己实现一个new 的话,首先要满足它的几点效果
一个构造函数会返回一个对象,那函数里就应该有对象
并将其
__proto__
属性指向构造函数的prototype
属性调用构造函数,绑定this
返回原始值需要忽略,返回对象需要正常处理
测试成果
实例代码:
new 操作符实现了如下的功能:
前面提到了隐式的返回,如果是显式返回呢?
构造函数如果返回基本类型,则还是会返回原来的 this (新对象)。如果返回的是引用类型,则返回该返回值。(可以自己在上面例子加上代码验证一下)
new 操作符的模拟实现
写个测试用例:
Reference
这个_new出来的对象调用原型上的方法会报错?
默写高赞...
new 都做了什么?
1、创建一个新的实例对象
2、将this指向新的实例对象
3、新对象的__proto__属性指向构造函数的原型对象
4、返回值
第一种实现:
第二种实现:
@Hiker9527
构造函数返回 String, Number, Boolean等对象也是可以的,而这些对象toString后并不是
[object Object]
这个题的题目描述是啥...
当然不是,这里判断构造函数执行的返回类型,如果构造函数执行结果返回的是个对象不就是true了
这样ret不是一直都是undefined吗?res instanceof Object就一直是false啊
写的真好
我也贴一个
function Dog(name) {
this.name = name
this.say = function () {
console.log('name = ' + this.name)
}
}
function Cat(name) {
this.name = name
this.say = function () {
console.log('name = ' + this.name)
}
}
function _new(fn, ...arg) {
const obj = {};
obj.proto = fn.prototype;
fn.apply(obj, arg)
return Object.prototype.toString.call(obj) == '[object Object]'? obj : {}
}
var dog = _new(Dog,'xxx')
dog.say() //'name = xxx'
console.log(dog instanceof Dog) //true
var cat = _new(Cat, 'carname');
cat.say() //'name = carname'
console.log(cat instanceof Cat) //true
之前写过一篇模拟实现
new
的文章~面试官问:能否模拟实现
JS
的new
操作符我的这篇文章主要提出了对返回值是函数和对象的处理,还有对
new.target
的简单处理。function _new(fn, ...arg) {
var obj = Object.create(fn.prototype);
fn.call(obj, ...arg);
let result = fn();
return Object.prototype.toString.call(result) == '[object Object]' ? result : obj;
}
@zwmmm 你是对的,我写的有点问题
这样写是不是简单点啊