惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Hackread – Cybersecurity News, Data Breaches, AI and More
S
Schneier on Security
罗磊的独立博客
Recorded Future
Recorded Future
Hacker News - Newest:
Hacker News - Newest: "LLM"
G
Google Developers Blog
博客园_首页
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
The Blog of Author Tim Ferriss
Know Your Adversary
Know Your Adversary
L
Lohrmann on Cybersecurity
C
Cybersecurity and Infrastructure Security Agency CISA
博客园 - 三生石上(FineUI控件)
M
MIT News - Artificial intelligence
B
Blog
T
Tor Project blog
D
Docker
Engineering at Meta
Engineering at Meta
Apple Machine Learning Research
Apple Machine Learning Research
Spread Privacy
Spread Privacy
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Scott Helme
Scott Helme
MyScale Blog
MyScale Blog
量子位
T
The Exploit Database - CXSecurity.com
小众软件
小众软件
aimingoo的专栏
aimingoo的专栏
IT之家
IT之家
AWS News Blog
AWS News Blog
Google Online Security Blog
Google Online Security Blog
NISL@THU
NISL@THU
D
DataBreaches.Net
Help Net Security
Help Net Security
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Cloudbric
Cloudbric
美团技术团队
W
WeLiveSecurity
H
Hacker News: Front Page
宝玉的分享
宝玉的分享
The Cloudflare Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
爱范儿
爱范儿
N
News and Events Feed by Topic
V
Visual Studio Blog
C
CERT Recently Published Vulnerability Notes
T
Tailwind CSS Blog
MongoDB | Blog
MongoDB | Blog
F
Fortinet All Blogs
B
Blog RSS Feed
S
Security Affairs

博客园 - 前端架构师

Claude Code 源码架构分析 我不是狐狸,我是那Harness Engineering 小龙虾的自我养成之路 vue3+ts添加公共富文本组件 vue watch详解 微信授权没搞过? css3图片防止变形 公众号使用微信sdk的正确姿势 web离线应用前提之离线检测 es6手写一个call this综合篇 this绑定番外篇之箭头函数绑定 vue中引入公用过滤器? this详解下 012天this详解上 011天之跨域资源共享CORS 010天JSON.stringify()详解 009天之跨浏览器的事件处理程序 使用XHR上传文件要不要了解一下?
同学给我来个手写的new吧
前端架构师 · 2020-03-22 · via 博客园 - 前端架构师

1.手写一个new

首先看看new怎么用

function Person(name){
    this.name = name
}
Person.prototype.eat = function() {
    console.log("Eating")
}
var qd = new Person('qd')
console.log(qd)
qd.eat();
  使用new创建的实例:
    能够访问构造函数里的属性(name);
    能够访问原型中的属性(eat)
在调用new时候发生了四件事:
    1新生成一个对象
    2将构造函数的作用域赋值给新对象(即绑定新对象的 this)
    3执行构造函数中的代码(即为这个新对象添加属性)
    4返回新对象

A版本

function create() {
    //1.获取构造函数,并删除arguments中的第一项
    var Con = [].shift.call(arguments);
    
    //2.创建一个空对象并连接到构造函数的原型,使它能够访问原型中的属性
    var obj = Object.create(Con.prototype);
    
    3.使用apply改变构造函数中this的指向实现继承,使obj能够访问到构造函数中的属性
    var ret = Con.apply(obj,arguments);
    
    4.优先返回构造函数返回的对象
    return ret instanceof Object ? ret : obj;
}

解释一下4中的判断:主要考虑的是没有返回值,

//1.有返回值且为对象:
function Person (name, sex) {
    this.name = name
    return {
        sex:sex
    }
}
1.构造函数中有返回值且为对象,那么创建的实例就只能访问到返回对象中的属性,
所以要判断一下ret的类型,如果是对象的话,则返回这个对象。

//2构造函数没有返回值:
function Person(name){
    this.name = name;
}
2.构造函数没有返回值,那么创建的实例就能访问这个构造函数中的所有属性了,此时ret就会为undefined,所以返回obj。

3,返回值为基本类型
function Person(name){
    this.name = name
    return 'str'
}
3.构造函数中没有返回值但是返回值是undefined以外的其他基本类型(比如字符串),这种情况当成第二种情况(没有返回值)来处理。

好了我们来验证一下吧:

function Person (name) {
    this.name = name
}
Person.prototype.eat = function() {
    console.log("Eating")
}

function create() {
    var Con = [].shift.call(arguments);
    var obj = Object.create(Con.prototype);
    var ret = Con.apply(obj, arguments);
    return ret instanceof Object ? ret : obj;
}

//调用
var qdleader = create(Person, 'qdleader');
console.log(qdleader); //Person{name:'LinDaiDai'}
qdleader.eat()  //'Eatting'





注意:object.create方法,参数为new出来的实例的原型,也就是_proto_的指向

还有其他版本的: b版本

function create() {
    // 创建一个空的对象
    let obj = {}
    // 获得构造函数
    // 因为 arguments 类数组,所以我们可以用数组的 shift 来实现 arguments 的 ‘push’ 和 ‘pop’
    // 将 arguments 进数组,并将第一个元素移除并赋值给 Con (Constructor).
    let Con = [].shift.call(arguments)
    // 链接到原型
    obj.__proto__ = Con.prototype
    // 绑定this,并执行构造函数,就相当于 obj .constructor(arguments)
    let result = Con.apply(obj, arguments)
    // 确保 new 出来的是个对象
    return typeof result === 'object' ? result : obj
}




1:arguments是一个类数组,以像是数组的样子取到传入的所有参数,有一个callee属性(值为被调用的方法)利用数组的shift方法拿到了第一项 也就是Animal函数,同时原来的arguments被更改,失去了第一个参数。再后面被apply拿来做参数

2:Constructor.apply(obj, arguments)
意思是在obj里执行构造函数,并且挨着arguments里剩下的参数

3:[ ]可以等价Array.prototype.shift ,也就是在arguments上执行数组的shift方法的意思

4:最后可以加一个判断,是否为对象再返回

比b版本更好一点的写法:

function _new() {
    let target = {}; //创建的新对象
    //第一个参数是构造函数
    let [constructor, ...args] = [...arguments];
    //执行[[原型]]连接;target 是 constructor 的实例
    target.__proto__ = constructor.prototype;
    //执行构造函数,将属性或方法添加到创建的空对象上
    let result = constructor.apply(target, args);
    if (result && (typeof (result) == "object" || typeof (result) == "function")) {
        //如果构造函数执行的结构返回的是一个对象,那么返回这个对象
        return result;
    }
    //如果构造函数返回的不是一个对象,返回创建的新对象
    return target;
}

个人感觉A版本好一些

欢迎加群!