在日常开发怎么选择每一个应用都是由各种组件组合而成

xzdxmynet 发布于 2024-04-25 阅读(27)

本文将结合两种常见的编程范式来回顾一下js语言层面的一些特性并理解视角。

编程范式

我们之前讨论过编程范例,让我们回顾一下它们:

我们在编程中解决的每个问题都对应于多个问题的组合,并且每种编程语言都实现一个或多个。

面向对象函数式的常见组合

OOP和FP是两种比较常见的编程范式,js也都支持。 有很多相关的讨论。 这里仅介绍其中一种观点。 更多细节将在后面的章节中介绍。

根据前面的说法,两种范式的区别在于 FP 比 OOP 少了一个状态,即

面向对象侧重于数据的各种处理。 数据是对象的内部状态。 C++ Plus 将对象的本质表达为用于设计和扩展自己的数据结构:

of - (OOP) 是和你自己的数据类型

函数式编程关注的是数据流的流动。 从外界输入数据,最终返回相应的结果。 函数式编程简介被概括为数据流而不是控制流。

核心是数据流而不是流

适用场景

以下结论参考vs[]

面向对象专家也表示:

OO 按部分编写代码。 FP 按部分编写代码。

面向对象的可读性是通过封装各个部分来实现的,而函数式可读性是通过最小化各个部分来实现的。 即前者封装了数据和数据动作,后者将各种操作进行拆分,使其最小化。

日常开发中如何选择

每个应用程序都是由各种组件组成的,但组件的形式并不固定,比如数据等。

不同的编程语言往往会使用不同的原子元素来组成组件,比如Java使用对象等,而在js中,由于天然支持面向对象和函数式编程,所以在项目中往往会混合使用它们。 我们可以使用对象组合来生成函数式编程的数据类型,并使用函数式编程生成对象来进行面向对象编程。 不管怎么写,软件开发的本质就是组合。

的 是

我们的工作就是根据不同的情况使用不同的编程范式,像盖房子一样组合不同的组件。 在详细讨论这两种范式之前,让我们首先了解一下 js 本身。

js中的相关功能

我们首先需要了解js语言的各种特性,然后才能使用范式这样的工具更好的结合我们开发的软件。 这部分主要是参考。

js语言设计

Eich开发了js。 在这篇文章中,他提到了js设计过程中的一些问题。

浏览器中需要内置脚本语言。 按照领导的要求,首先要像java(看起来像Java,所以很多语法都和java类似)。 作者更喜欢它,所以最终选择了与 First-class Functions 相同的语言以及与 Self 相同的语言作为主要组件。 受Java的影响,原始类型和对象之间存在着和的区别。

上面的设计以及后续的开发就成为了现在的js。

js特性概述

js中有两种数据结构,原始类型和对象。 js中的对象创建不是基于类的,而是有很多方法,比如字面量或者构造函数。 每个构造函数都有一个用于实现的属性。 基于原型(-based)的继承。 构造函数还具有对构造函数本身的引用。 当实现继承时,该属性可能会发生变化,需要按照约定进行更正,但这不是必需的(更多信息请参见此处)。

说到构造函数,这里有一些相关的概念。 函数是包含[[Call]]的特殊对象,因此可以通过函数调用来执行相关代码,而构造函数是包含[[ ]]的特殊函数,可以通过new或super调用创建对象。

js中的对象原型链

通过构造函数创建的每个对象都有一个对构造函数属性的隐式引用(可以访问但不推荐),该属性本身可能有一个对其的非空引用等。这称为原型链。 当访问对象的属性时,会首先从对象本身开始查找。 如果找不到,则沿着原型链查找,直到找到或者最后发现没有找到。 原型链上的属性可以被覆盖。

与基于类继承的语言相比,一般来说,状态归实例所有,方法归类所有,只有结构体和行为()被继承,但js所有的都可以继承。 这里。

原型链的末尾为空。 为了明确对象的原型链包含哪些内容,大致可以分为以下几种

var obj={}
//原型链 obj=>Object.prototype=>null

var arr =[]
//arr=>Array.prototype=>Object.prototype=>null
//如果是自定义构造函数也一样
var P=function(){}
var p=new P()
//p=>P.prototype=>Object.prototype=>null

//1. 使用Object.create()
var q=Object.create(p)
// q=>p
//2. 直接修改构造函数的prototype
function Q(){}
Q.prototype=p
var q=new Q()
//q=>p
//3. 通过Object.setPrototypeOf(obj, prototype)设置__proto__属性,可以直接修改原型链,这个操作很浪费性能,少用
function P(){
    this.b=1
}
function Q(){
    this.a=2
}
var q=new Q()
Object.setPrototypeOf(q,P.prototype)
// q=>P.prototype
//4. 使用call和apply借用构造函数时,和原型无关
var P=function(v){
    this.a=v
}
function Q(v){
    P.call(this,v)
}
var q=new Q(2)
// q=>Q.prototype=>Object.prototype=>null

我们可以判断一个构造函数是否在指定对象的原型链中

function Q(){
    this.a=2
}
var q=new Q()
console.log(q instanceof Q)
console.log(q instanceof Object)

可以通过.()获取对象的属性

上有一些属性和方法。 被所有其他对象继承,并且某些字段可能在特定对象的继承过程中被覆盖。

另外,还有很多静态方法用于处理对象的各种操作。 详情请参阅

js中的函数

js中的所有函数都是 , 包括 和 本身的实例,甚至还有各种内置构造函数(如Array),因此有

Function.__proto__===Function.prototype//true
Function.prototype.__proto__===Object.prototype//true,即Function instanceof Object
//原型链 Function=>Function.prototype=>Object.prototype,以下类似
Object.__proto__===Function.prototype//true,即Object instanceof Function
Array.__proto__===Function.prototype //true
function a(){}
a.__proto__===Function.prototype//true

可见,在到达之前都需要传递所有函数的原型链。 函数是一个对象和一个函数。

标签:  函数 对象 编程 构造 原型 

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。