探索ES6类构造器中创建原型同名变量的原理
2020/4/1 11:01:35
本文主要是介绍探索ES6类构造器中创建原型同名变量的原理,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
2020/03/25
我开始学习react
当看到react
在创建组件时this
绑定问题的时候起了疑问:
ES6中class中所写的方法默认时在原型对象上的
当时我使用ES5的思维:
function Person(name,age){ this.name = name; this.age = age; } Person.prototype.sayName = function(){ return this.name; }; 复制代码
在ES6中使用class
class Person{ constructor(name,age){ this.name = name; this.age = age; } //1. sayName = function(){} 是创建实例方法 //2. static sayName(){} 是创建静态方法 Person.sayName //3. sayName(){} 是创建原型方法 sayName(){ return this.name; } } 复制代码
我在react创建组件绑定事件的过程中看到了如下代码,满脸问号ES6的class不只是一个语法糖么?
class Person{ state = {};//创建state constructor(props){ this.handleClick = this.handleClick.bind(this);//这是啥?我有这属性? } handleClick(e){ //doSomething } render(){/* return (<div>...</div>) */} } 复制代码
What? && Why?
「this.handleClick = this.handleClick.bind(this);
」
既然问题迎面而来,那么接下来开始分析之旅吧?
1.通过Chrome的F12我了解到是原型上和实例上都是有一个同名属性
2.原型上的属性是普通的方法,实例(obj)上的属性是此方法调用Function.prototype.bind(obj)返回的bound
那么什么是bound呢? 如果你对bound了解了,那么可以尝试看一下github上我写了一个bind的实现原理
//New的实现 function New(constructor, ...args) { let o = {}; constructor = typeof constructor === 'function' ? constructor : function() {}; o.__proto__ = constructor.prototype; //这一步骤决定最后打印出来的o这个对象的类型 let returnVal = constructor.Apply(o, args); //至于打印出来的对象标识 取决于 原型上的constructor属性指向的函数名字,而这个name属性是无法改变的 //这里的returnVal会一直被引用,这里只是一个概念,应该通过参数传递,这里使用之后赋值null return returnVal && typeof returnVal === 'object'? returnVal : o; } //Call的实现 Function.prototype.Call = function(that) { //这里需要一个不会重复的键值作为{key:value}中的key const fn = Symbol('fn'); //如果不是用ES6中的Symbol 自己创建一个(Math.random() + new Date().getTime()).toString(32).slice(8) //这里将除that外的参数列表转换为数组,以为arguments中有Symbol.iterator所以可以使用of和...这两个操作 //其实还可以使用 Array.prototype.slice.call(arguments).slice(1); const args = [...arguments].slice(1); //如果that 为 undefined/null 这时this指向window that = that || window; //将独一无二的key 配上 value:Call的调用函数 that[fn] = this; //执行这个函数,并将结果在最后返回 const res = that[fn](...args); //不要忘记删除这个属性 delete that[fn]; return res; }; //Apply的实现 Function.prototype.Apply = function(that) { let fn = Symbol('fn'); let args = arguments[1]; that = that || window; //undefined / null that ->window that[fn] = this; let res = that[fn](...args); delete that[fn]; return res; }; //Bind的实现依赖Apply/Call Function.prototype.Bind = function(that) { that = that && (typeof that === 'object' || typeof that === 'function') ? that : window; let args = Array.prototype.slice.call(arguments).slice(1); let self = this; let bound = function() { //判断是否通过new调用这个函数 //如果是 new bound(),构造函数中的this被绑定到了一个被指定__proto__ == <constructor>.prototype //这时候使用 this instanceof pure return self.Apply(Instanceof(this, bound) ? this : that, args.concat(...arguments)); } //箭头函数的prototype是undefined //这里吧bound.prototype 改变到了调用bind函数的self上 if (self.prototype) { bound.prototype = self.prototype; } return bound; } 复制代码
最后通过babel将ES6转成ES5解决了我的疑问
这里用到的知识点
1.闭包Closure
2.变量提升function var
这篇关于探索ES6类构造器中创建原型同名变量的原理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-28一步到位:购买适合 SEO 的域名全攻略
- 2024-12-27OpenFeign服务间调用学习入门
- 2024-12-27OpenFeign服务间调用学习入门
- 2024-12-27OpenFeign学习入门:轻松掌握微服务通信
- 2024-12-27OpenFeign学习入门:轻松掌握微服务间的HTTP请求
- 2024-12-27JDK17新特性学习入门:简洁教程带你轻松上手
- 2024-12-27JMeter传递token学习入门教程
- 2024-12-27JMeter压测学习入门指南
- 2024-12-27JWT单点登录学习入门指南
- 2024-12-27JWT单点登录原理学习入门