首页 > 编程语言 >NodeJS对象模型

NodeJS对象模型

时间:2023-07-20 14:14:25浏览次数:51  
标签:console log Point 对象 模型 NodeJS constructor show name

四、JS对象模型

目录

JavaScript 是一种基于原型(Prototype)的面向对象语言,而不是基于类对象的面向对象语言

C++、JAVA 有类Class和实例intance的概念,类是一类事物的抽象,而实例是类的实体

JS 是基于原型的语言,它只有原型对象的概念,原型对象就是一个模板,新的对象从这个模板构建从而获取最初的属性。任何对象都可以在运行时动态增加属性,而且任何对象都可以作为另一个对象的原型,这样后者就可以共享前者的属性。

定义类

字面声明方式定义

var obj = {
    name: 'dengyou',
    func: (x, y) => x+y,
}

console.log(obj.name)
console.log(obj.func)
console.log((obj.func)(10, 20))
输出结果:
dengyou
[Function: func]
30

ES6之前-构造器

  • 定义一个函数(构造器对象),函数首字母大写
  • 使用this定义属性
  • 使用new关键字和构造器创建新对象
// 定义一个构造器
function Point(x, y) {
    this.x = x;
    this.y = y;
    this.show = () => console.log(this, this.x, this.y)
    console.log("Point ~~~~~~~~~~~~~")
}

// 创建对象
p1 = new Point(4, 5);  
console.log(p1);
console.log(p1.x);
p1.show();

输出结果:
Point ~~~~~~~~~~~~~
Point { x: 4, y: 5, show: [Function] }
4
Point { x: 4, y: 5, show: [Function] } 4 5
  • 继承
// 定义一个构造器
function Point(x, y) {
    this.x = x;
    this.y = y;
    this.show = () => console.log(this, this.x, this.y)
    console.log("Point ~~~~~~~~~~~~~")
}

// 继承
function Point3D(x,y,z) {
    Point.call(this, x, y);
    this.z = z;
    this.show = () =>  console.log(this, this.x, this.y, this.z)
    console.log("Point3D ~~~~~~~~~~")
}

p2 = new Point3D(4, 5, 6)
console.log(p2)
p2.show()

输出结果:
Point ~~~~~~~~~~~~~
Point3D ~~~~~~~~~~
Point3D { x: 4, y: 5, show: [Function], z: 6 }
Point3D { x: 4, y: 5, show: [Function], z: 6 } 4 5 6

class 关键字构建

从ES6开始,提供class关键字,使得创建对象更加简单,清晰

  • 类定义使用关键字。创建的本质还是函数
  • 一个类只能拥有一个名为constructor的构造方法
  • 继承使用extends关键字
  • 一个构造器可以使用super关键字来调用一个父类的构造函数
  • 类没有私有属性
class Point {
    constructor(x, y) /*构造器*/ {
        this.x = x;
        this.y = y;
    }
    show() /*方法*/ {
        console.log(this, this.x, this.y)
    }
}

let p1 = new Point(10, 11)
p1.show()
  • 继承
// 定义一个基类
class Point {
    constructor(x, y) /*构造器*/ {
        this.x = x;
        this.y = y;
    }
    show() /*方法*/ {
        console.log(this, this.x, this.y)
    }
}

// let p1 = new Point(10, 11)
// p1.show()

// 继承
class Point3D extends Point {
    constructor(x,y,z) {
        super(x,y);
        this.z = z;
    }
}

let p2 = new Point3D(10,11,12)
p2.show()

重写方法

  • 重写子类的show方法, 如果要使用父类的方法,使用 super.method()调用
class Point {
    constructor(x, y) /*构造器*/ {
        this.x = x;
        this.y = y;
    }
    show() /*方法*/ {
        console.log(this, this.x, this.y)
    }
}

// let p1 = new Point(10, 11)
// p1.show()

// 继承
class Point3D extends Point {
    constructor(x,y,z) {
        super(x,y);
        this.z = z;
    }
    show() /*重写*/ {
        console.log(this, this.x, this.y, this.z)
    }
}

let p2 = new Point3D(10,11,12)
p2.show()

使用箭头函数重写上面的方法

// 定义一个基类
class Point {
    constructor(x, y) /*构造器*/ {
        this.x = x;
        this.y = y;
        this.show = () =>  console.log('Point method'); //2
    }  
    show() {console.log("Point function method")} //4
  
}
// 继承
class Point3D extends Point {
    constructor(x,y,z) {
        super(x,y);
        this.z = z;
        this.show = () =>  console.log('Point3D method'); // 1
    }  
    show() {console.log("Point3D function method")}  //3
}

let p2 = new Point3D(10,11,12)
// 优先使用类的属性,如果没有会查找父类的属性,如果还没找到会查找类的方法,最后查找父类的方法,优先级为1,2,3,4
p2.show()

对于方法重写而言,父类,子类使用同一种方式定义方法,子类覆盖父类;如果父类使用属性,子类使用方法,则优先使用父类的属性。一句话,属性优先

静态属性

静态属性目前还没有得到很好的支持

静态方法

在方法名前面加上static,就是静态方法了。

class Add {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    static print() {
        console.log(this, this.x)
    }
}

Add.print() // [class Add] undefined

add = new Add(4,5)
add.constructor.print() // 实例不能直接访问静态方法,可以通过constructor访问

输出结果:
[class Add] undefined
[class Add] undefined

this 的坑

C++,JAVA,JS都有this,但是C++跟JAVA都是编译型语言,this是编译的时候就绑定了,而JS是动态语言,是在运行期进行绑定的,所以他们的表现各不相同,对于JS而言,调用方式的不同,this对应的对象也就不同了。

var school = {
    name: 'dengyou',
    getNameFunc: function() {
        console.log(this.name);
        console.log(this);
        return function() {
            console.log(this === global)
            return this.name
        }
    }
}

ret = school.getNameFunc()
console.log("---------------")
console.log(ret())

输出结果:
dengyou  
{ name: 'dengyou', getNameFunc: [Function: getNameFunc] }
---------------
true  // 说明this当前是global,nodejs函数调用的global,浏览器中的全局对象是windows
undefined // 因为this为全局对象,所以没有name属性

对于上面的例子,调用方式的不同,this对应的对象也有所变化,这种变化是历史遗留问题,我们使用是,需要明确的让this必须是我们期望的对象,可以通过下面几种方式解决这个问题。

显示传入-that

通过主动传入对象,避免this的问题,这个我们不推荐使用

var school = {
    name: 'dengyou',
    getNameFunc: function() {
        console.log(this.name);
        console.log(this);
        return function(that) /*传入that*/ {
            console.log(this === global)
            return that.name
        }
    }
}

ret = school.getNameFunc()
console.log("---------------")
console.log(ret(school))

输出结果:
dengyou
{ name: 'dengyou', getNameFunc: [Function: getNameFunc] }
---------------
true
dengyou

ES3 引入apply、call方法

apply、call方法都是函数对象的方法,第一参数都是传入对象引入的

var school = {
    name: 'dengyou',
    getNameFunc: function() {
        console.log(this.name);
        console.log(this);
        return function() {
            console.log(this === global)
            return this.name
        }
    }
}

ret = school.getNameFunc()
console.log("---------------")
console.log(ret.call(school))  // 等价console.log(ret.apply(school))
  • apply传入其他参数需要使用数组
  • call传入其他参数需要使用可变参数收集
function Print() {
    this.print = function(x, y) {console.log(x, y)}
}

p = new Print(1,2)
p.print(10,20)

p.print.call(p, 10,20)
p.print.apply(p, [10, 20])

输出结果:
10 20
10 20
10 20

ES5 引入bind方法-常用

bind方法来设置函数的this值


var school = {
    name: 'dengyou',
    getNameFunc: function() {
        console.log(this.name);
        console.log(this);
        return function() {
            console.log(this === global)
            return this.name
        }
    }
}

ret = school.getNameFunc()
console.log("---------------")
console.log(ret.bind(school)/*绑定以后再调用*/())

ES6引入支持this的箭头函数-推荐

var school = {
    name: 'dengyou',
    getNameFunc: function() {
        console.log(this.name);
        console.log(this);
        return() => { /*箭头函数*/
            console.log(this === global)
            return this.name
        }
    }
}

ret = school.getNameFunc()
console.log("---------------")
console.log(ret())
// 将上面的类改写为新的类
class School {
    constructor() {
        this.name = 'dengyou'
    }
    getNameFunc() {
        console.log(this.name);
        console.log(this, typeof(this));
        return () => {
            console.log(this === global)
            return this.name
        }
    }
}

console.log(new School().getNameFunc()())
输出结果:
dengyou
School { name: 'dengyou' } object
false
dengyou

高阶对象、高阶类、或称 Mixin 模式

Mixin模式,混合模式,这是一种不用继承就可以复用的技术,主要是为了解决多重继承的问题,多继承的继承路径是一个问题

JS是基于对象的,类和对象都是对象模板

混合mixin,指的是将一个对象的全部或部分属性拷贝到另一个对象上去,可以将多个类或者对象混合成一个类或者对象

继承实现

先看一个继承的例子

class Serialization {
    constructor() {
        console.log('Serialization constructor~~~~~~~')
        /* 要求具有属性 stringify ,如果没有则抛出异常*/
        if (typeof(this.stringify) != 'function') {
            throw new ReferenceError("should define stringify method")
        }
    }
}

class Point extends Serialization {
    constructor(x, y) {
        console.log("Point constructor~~~~~~~~~~ ")
        super(); // 调用父的构造器
        this.x = x;
        this.y = y;
    }

    stringify() {
        return `<Point x=${this.x},y=${this.y}>}`
    }
}


class Point3D extends Point {
    constructor(x,y,z) {
        super(x,y);
        this.z = z;
    }
    stringify() {
        return `<Point3D x=${this.x},y=${this.y}, z=${this.z}>}`
    }

}

let p  = new Point(4, 5)
console.log(p.stringify())
console.log("+++++++++++++++++++++++++++")
let p3d = new Point3D(4,5,6)
console.log(p3d.stringify())

输出结果:
Point constructor~~~~~~~~~~ 
Serialization constructor~~~~~~~
<Point x=4,y=5>}
+++++++++++++++++++++++++++
Point constructor~~~~~~~~~~ 
Serialization constructor~~~~~~~
<Point3D x=4,y=5, z=6>}

高阶对象的实现

const Serialization = Sup => class extends Sup {
    constructor(...args) {
        console.log('Serialization constructor~~~~~~~')
        super(...args)
        if (typeof(this.stringify) != 'function') {
            throw new ReferenceError("should define stringify method")
        }
    }
}

class Point {
    constructor(x, y) {
        console.log("Point constructor~~~~~~~~~~ ")
        this.x = x;
        this.y = y;
    }
}

class Point3D extends Serialization(Point) /*Serialization(Point)匿名箭头函数调用,返回一个新的类型*/ {
    constructor(x,y,z) {
        super(x,y);
        this.z = z;
    }
    stringify() {
        return `<Point3D x=${this.x},y=${this.y}, z=${this.z}>}`
    }

}

let p3d = new Point3D(4,5,6)
console.log(p3d.stringify())

输出结果:
Serialization constructor~~~~~~~
Point constructor~~~~~~~~~~ 
<Point3D x=4,y=5, z=6>}

标签:console,log,Point,对象,模型,NodeJS,constructor,show,name
From: https://www.cnblogs.com/kntvops/p/17568110.html

相关文章

  • java怎么把hashset中的对象取出来
    项目方案:Java中HashSet中对象的提取方案1.简介本项目方案旨在解决在Java中如何从HashSet中提取对象的问题。HashSet是Java集合框架中的一种常用集合类型,它类似于List和Set,但不允许包含重复元素。因此,当我们需要从HashSet中提取对象时,需要遵循特定的操作步骤。2.方案设计为......
  • 建立模型类常见的配置
    classUser(AbstractUser):mobile=models.CharField(max_length=16,unique=True)avatar=models.ImageField(upload_to='avatar',default='avatar/default.png')#ImageField继承自filefield需要pillow模块的支持classMeta:db_......
  • 发布-订阅(Publish-and-Subscribe)模型
    发布-订阅(Publish-and-Subscribe)模型是一种消息传递模式,用于在软件系统中实现异步通信和解耦。它基于发布者(发布消息的实体)和订阅者(接收和处理消息的实体)之间的解耦原则。在发布-订阅模型中,发布者和订阅者之间不直接交互,而是通过一个称为消息代理或消息中间件的组件来进行通信。......
  • 10分钟带你学会阿里OSS对象存储
    一.前言最近有很多小伙伴问健哥,如果我们要进行大规模的文件存储该怎么做?其实实现文件存储的技术有很多,如果我们在网上搜索一下,你会发现实现的技术简直是五花八门,比如有一种技术叫FastDFS就可以实现文件存储,但该方案需要自己搭建服务器,非常的麻烦。实际上现在很多公司都在使用......
  • Matlab马尔可夫区制转换动态回归模型估计GDP增长率|附代码数据
    原文链接:http://tecdat.cn/?p=19918最近我们被客户要求撰写关于马尔可夫区制转换动态回归的研究报告,包括一些图形和统计输出。本文估计实际GDP增长率的两状态Markov区制转换动态回归模型  ( 点击文末“阅读原文”获取完整代码数据******** )。创建模型进行估计通过指定转移......
  • R语言泊松Poisson回归模型分析案例|附代码数据
    原文链接:http://tecdat.cn/?p=2605最近我们被客户要求撰写关于泊松Poisson回归的研究报告,包括一些图形和统计输出。这个问题涉及马蹄蟹研究的数据。研究中的每只雌性马蹄蟹都有一只雄性螃蟹贴在她的巢穴中。这项研究调查了影响雌蟹是否有其他男性居住在她附近的因素。被认为影......
  • 大模型FAQ
    BERT主要的创新之处是什么BERT(BidirectionalEncoderRepresentationsfromTransformers)是一种基于Transformer架构的预训练语言模型,由Google在2018年提出。它的创新之处主要包括以下几个方面:双向性(Bidirectional):BERT是第一个采用双向Transformer架构进行预训练的模型。传统的......
  • MATLAB用GARCH-EVT-Copula极值理论模型VaR预测分析股票投资组合|附代码数据
    全文链接:http://tecdat.cn/?p=30426最近我们被客户要求撰写关于GARCH-EVT-Copula的研究报告,包括一些图形和统计输出。对VaR计算方法的改进,以更好的度量开放式基金的风险。本项目把基金所持股票看成是一个投资组合,引入Copula来描述多只股票间的非线性相关性,构建多元GARCH-EVT-Cop......
  • list过滤对象
    Stringlocal=LocalDate.now().toString().replaceAll("-","").substring(0,6);System.out.println("---------------"+local);IntegerlocalYearMonth=Integer.valueOf(local);booleanb=Objects.nonNull(dept4);List<Dept>......
  • 大前端一篇文章搞定什么是nodeJs它和NPM关系与应用
    现在前端的入门门槛越来越高了,不再是单纯 html+css+js,各种前端框架层出不穷,各种ui组件库层出不穷。模块化,打包化,各种工具库层出不穷,前端变成大前端 ,甚至前端可以搞定整个项目,通过node作为服务端api,这里我们主角就是nodeJs什么是nodejsjavaScript是一门脚本语言,通常被用来......