JS优雅的使用function实现一个class

目录
  • 正文
    • Tip1:class只能通过new调用
    • Tip2:class中的函数不能被枚举
    • Tip3:class中的函数不能被new调用
    • Tip4:在ES6中使用类语法,代码都是在严格模式下运行

正文

使用function来写出一个class的类对于我们来说当然是简单的,但必须注意的是,要做好function实现一个class,那么就要必须实现达到高精准度的模仿,把该实现的细节都实现好,才能更好的对class进行深入的理解

废话少说,开始写出我们的class

class MyClass{
    constructor(name){
        this.name = name
    }
    fun(){
        console.log('myName:'+this.name)
    }
}

这是一个平平无奇的class,接着我们使用function来对其进行一下实现。

function MyClass1(name){
    this.name = name
}
MyClass1.prototype.fun = function(){
    console.log('myName:'+this.name)
}
let m1 = new MyClass1('aaa')
m1.fun() //myName:aaa

让我们继续完善一下function的实现,我们先一步一步来

Tip1:class只能通过new调用

class MyClass{
    constructor(name){
        this.name = name
    }
    fun(){
        console.log('myName:'+this.name)
    }
}
// MyClass('aaa') //TypeError: Class constructor MyClass cannot be invoked without 'new'

对于类的调用,只能通过new来进行实例化,而不能通过直接调用,下面我们在function来实现这个操作

如何判断是通过new调用而不是通过直接调用,这个时候this的熟练度就显得比较重要了,不熟悉也不要急,让我们一起来打印看看

function MyClass1(name){
    console.log(this)
    this.name = name
}
let m1 = new MyClass1('aaa') //MyClass1 {}
MyClass1('aaa') //window
  • 对于new调用,函数内部的this指向构造函数 (new绑定)
  • 直接调用 那么很明显this指向的是全局(默认绑定)

根据这个特点,在构造函数里面判断this的指向,从而抛出报错,即可实现class的效果

function MyClass1(name){
    console.log(this)
    if(!(this instanceof MyClass)){ //如果this不是指向MyClass
        throw new TypeError('TypeError: Class constructor MyClass cannot be invoked without 'new'')
    }
    this.name = name
}

Tip2:class中的函数不能被枚举

let m = new MyClass('aaa')
for(let i in m){
    console.log(i) //name
}
let m1 = new MyClass1('aaa')
for(let i in m1){
    console.log(i) //name fn
}

从上可以看出类中的函数不能被枚举出来,枚举我们就想到了enumerable,也就是Object.defineProperty来对原型上的fn进行设置

'use strict'
function MyClass1(name){
    this.name = name
}
Object.defineProperty(MyClass1.prototype,'fn',{
    value:function(){
        console.log('myName:'+this.name)
    },
    enumerable:false
})

好的,我们离完美又更近了一步。

Tip3:class中的函数不能被new调用

同样是new调用的方式,不能对类中的函数进行new调用

let m = new MyClass('aaa')
new m.fun() //TypeError: m.fun is not a constructor

在这里会抛出一个错误,所以在用function实现类的时候也要避免这个问题,function中的函数都是可以通过new来进行调用的,我们来进行修改,有了上面对new的判断经验,很容易来解决这个问题

Object.defineProperty(MyClass1.prototype,'fn',{
    value:function(){
        //不可通过new调用
        console.log(this) //正常调用下的this是指向实例 MyClass1 { name: 'aaa' }
        if(!(this instanceof MyClass1){//那么相反 不是正常调用的就是错误的调用
            //error
        }
        console.log('myName:'+this.name)
    },
    enumerable:false
})

同样使用this的判断来看下是不是通过new的调用,正常调用下的this是指向实例 MyClass1,那么相反 不是正常调用的就是错误的调用

最后是一个小小的细节

Tip4:在ES6中使用类语法,代码都是在严格模式下运行

所以对于function的代码,需要在前面加上’user strict‘

'use strict'
function MyClass1(name){
    this.name = name
}
Object.defineProperty(MyClass1.prototype,'fn',{
    value:function(){
        console.log(this)
        if(!(this instanceof MyClass1)){
            //error
            throw TypeError('error')
        }
        console.log('myName:'+this.name)
    },
    enumerable:false
})
let m1 = new MyClass1('aaa')
m1.fn()
// new m1.fn() //error
for(let i in m1){
    console.log(i) //name
}

恭喜你认真的看完了,希望你也能学习到一点~

到这里我们就完结撒花啦~~

以上就是JS优雅的使用function实现一个class的详细内容,更多关于JS使用function实现class的资料请关注我们其它相关文章!

(0)

相关推荐

  • Vue开发手册Function-based API RFC

    目录 概要 基本例子 设计动机 逻辑组合与复用 类型推导 设计细节 setup() 函数 组件状态 为什么需要包装对象? Ref Unwrapping(包装对象的自动展开) 配合手写 Render 函数使用 Watchers Watcher 回调的调用时机 生命周期函数 依赖注入 类型推导 纯 TypeScript 的 Props 类型声明 复杂 Props 类型 缺点/潜在问题 升级策略 附录 Class API 的类型问题 概要 2020 年一月又注:RFC 已经被完全重写,最新版本请以 h

  • React Hook 'useEffect' is called in function报错解决

    目录 总览 声明组件 声明自定义钩子 总结 总览 为了解决错误"React Hook 'useEffect' is called in function that is neither a React function component nor a custom React Hook function",可以将函数名的第一个字母大写,或者使用use作为函数名的前缀.比如说,useCounter使其成为一个组件或一个自定义钩子. 这里有个示例用来展示错误是如何发生的. // App.j

  • react component function组件使用详解

    目录 不可改变性 虚拟dom与真实dom 函数组件 组件复用 纯函数 组件组合--组件树 组件抽离 不可改变性 1.jsx- 2.component(function)-component(class)-components(函数组件组合)-component tree(redux)-app(项目开发) 在react中,创建了js对象(react元素)就是不可更改的(immutable).就像是用相机拍照,相当于在此时间点已经定位了时间节点,只能拍下一张照片. 例如,使用底层react写一个时钟

  • Vue+Element-ui弹窗 this.$alert is not a function问题

    目录 Vue Element-ui弹窗 this.$alert is not a function 使用问题 解决办法 Vue element-ui 弹窗使用遇到的问题 解决代码如下 Vue Element-ui弹窗 this.$alert is not a function 使用问题 Element-ui官网上单独引用MessageBox的话需要在import中加入MessageBox. 但是在使用时报了this.$alert is not a function 解决办法 在element.j

  • React报错map() is not a function详析

    目录 总览 Array.isArray Array.from Object.keys 总览 当我们对一个不是数组的值调用map()方法时,就会产生"TypeError: map is not a function"错误.为了解决该错误,请将你调用map()方法的值记录在console.log上,并确保只对有效的数组调用map. 这里有个示例来展示错误是如何发生的. const App = () => { const obj = {}; // ️ Uncaught TypeErro

  • JS优雅的使用function实现一个class

    目录 正文 Tip1:class只能通过new调用 Tip2:class中的函数不能被枚举 Tip3:class中的函数不能被new调用 Tip4:在ES6中使用类语法,代码都是在严格模式下运行 正文 使用function来写出一个class的类对于我们来说当然是简单的,但必须注意的是,要做好function实现一个class,那么就要必须实现达到高精准度的模仿,把该实现的细节都实现好,才能更好的对class进行深入的理解 废话少说,开始写出我们的class class MyClass{ con

  • JS简单判断字符在另一个字符串中出现次数的2种常用方法

    本文实例讲述了JS简单判断字符在另一个字符串中出现次数的2种常用方法.分享给大家供大家参考,具体如下: 经过搜索验证,提供两个方法. 1. 通过分割获取长度原理 var s = 'www.jb51.net'; var n = (s.split('.')).length-1; alert(n); //弹出2 2. 通过正则实现 function patch(re,s){ re=eval("/"+re+"/ig") return s.match(re).length;

  • 纯JS焦点图特效实例(可一个页面多用)

    实例如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Co

  • 一个Js文件函数中调用另一个Js文件函数的方法演示

    我们知道,在html中,利用<script language="javascript" type="text/javascript" src="./script.js"></script>引入的两个js是不可以相互调用的.那么该如何解决呢?当然,你可以将代码通通copy过来,也许你并不喜欢这样. 例如有这样一个html,里面有一个按钮,当按下时调用b.js文件中的方法b().而b()中又要调用a.js文件中的方法a().若

  • 通过js脚本复制网页上的一个表格的不错实现方法

    今天有人问我一个问题:如何通过js脚本复制网页上的一个表格?看起来似乎比较有难度,不过还是搞定了,顺便把解决这个问题的过程记录下来,希望能对写脚本的兄弟们有所帮助. 以前没有写过这种脚本,不过想起来前不久刚看到一个脚本可以实现全选HTML编辑器的内容,于是想到一个方案:使用脚本将该表格插入HTML编辑器中,然后全选HTML编辑器内容,执行HTML编辑器的复制命令,即可实现复制表格功能,很快搞定: 测试 测试表格 测试表格 测试表格 测试表格 文字 "); // 初始化编辑器 editor.doc

  • 解决JS表单验证只有第一个IF起作用的问题

    文章来自:https://blog.csdn.net/qq_38215042/article/details/84675988 具体代码如下所述: if(条件语句){ return false; }else{ return true; } if(条件语句){ return false; }else{ return true; } if(条件语句){ return false; }else{ return true; } 你写的是不是上面这种情况?其实会出现只执行了第一个这种情况,主要是你在if

  • js删除对象中的某一个字段的方法实现

    本文主要介绍了js删除对象中的某一个字段的方法实现,分享给大家,具体如下: // 以下方法不改变原来对象 let item = { name:'张三', age:'18', gender:'男' }; console.log(item) // {age: "18",gender: "男",name: "张三"} let { age,...params } = item; console.log(item) // {age: "18&qu

  • JS实现在网页中弹出一个输入框的方法

    本文实例讲述了JS实现在网页中弹出一个输入框的方法.分享给大家供大家参考.具体分析如下: 习惯了使用早期给电脑文件夹设置密码的朋友一定还记得那种弹出一个输入框,然后让你输入密码在登录查看的效果吧,这个JS代码就是实现这个在当前页面中弹出一个输入框,当然你可以输入任何东西 <html> <head> <title>js输入对话框</title> </head> <body> <script language="javas

  • IE6下js通过css隐藏select的一个bug

    今天遇到一个问题, 当隐藏表格行 Tr 时 $id("tr_" + id + "_1").style.setAttribute('cssText',"display:none;");, 表格行 Tr 里面的 select 在 IE6 中隐藏不了,还是会显示在页面当中.想单独设置 select 的样式为隐藏 $id("new_attpm_id2_" + id).style.setAttribute('cssText',"

  • JS使用iView的Dropdown实现一个右键菜单

    前言 前段时间在用iView做个项目,其中需要使用自定义的右键菜单,然后去官网找了一下,发现有个Dropdown的组件,便想着能不能用来做个右键菜单的组件 你可能需要对iView有一定的使用经验 尝试 Dropdown的使用大概是这个样子 <template> <Dropdown> <a href="javascript:void(0)" rel="external nofollow" > 下拉菜单 <Icon type=&

随机推荐