【原型详解】JavaScript原型链:深入了解Prototype,超级详细!!!

news2024/11/20 3:22:56

在这里插入图片描述

😁 作者简介:一名大四的学生,致力学习前端开发技术
⭐️个人主页:夜宵饽饽的主页
❔ 系列专栏:JavaScript进阶指南
👐学习格言:成功不是终点,失败也并非末日,最重要的是继续前进的勇气

​🔥​前言:

有关对象中的原型和原型链,这里面有很多的知识体系,对于构造函数和所谓的原型继承到底是什么?,对于constructor的理解比较模糊,还有在javaScript中所谓的“类”和对象是什么关系?这些问题在本篇都可以了解到,请大家认真理解本篇博客,会受益匪浅的,希望可以帮助到大家,欢迎大家的补充和纠正

文章目录

  • 原型
    • 1 [[ Prototype ]]
    • 2 属性设置和屏蔽
    • 3 类
      • 3.1 “类”函数
      • 3.2 构造函数与类的误解
      • 3.3 构造函数是什么
      • 3.4 构造函数的属性是什么
      • 3.5 实例的constructor属性
      • 5.3 (原型)继承
    • 4 对象关联
      • 4.1 创建关联
      • 4.2 关联关系的意义

原型

1 [[ Prototype ]]

JavaScript 中的对象有一个特殊的 [[Prototype]] 内置属性,其实就是对于其他对象的引用。几乎所有的对象在创建时 [[Prototype]] 属性都会被赋予一个非空的值

🤔 思考以下代码:

//第一种情况
var myObject={
	a:2
}

//当对象上有这个属性时
myObject.a //2

//第二种情况
var anotherObject={
    a:2
}
// 创建一个关联到 anotherObject 的对象
var myObject=Object.create(anotherObject)
//当对象上没有,对象的原型上有时
myObject.a //2

当我们引用对象属性时会触发Get操作。比如上述代码中myObject.a。

  • 第一步会检查myObject对象本身是否有这个属性,如果有就用它
  • 当myObject对象本身没有时,会进行第二步,检查myObject对象的[[Prototype链]](代码中是anotherObject对象)
  • 如果 anotherObject 中也找不到 a 并且 [[Prototype]] 链不为空的话,就会继续查找下去
  • 这个过程会持续找到匹配的属性名或者完整条[[Prototype]]链,如果后者的话,Get操作会返回undefined

2 属性设置和屏蔽

当我们给对象设置属性并不是仅仅是添加一个新属性或者修改已有的属性值

接下来,我们完整的讲解一下这个过程:

myObject.foo='bar'
  • 如果 myObject 对象中包含名为 foo 的普通数据访问属性,这条赋值语句只会修改已有的属性值
  • 如果 foo 不是直接存在于 myObject 中,[[Prototype]] 链就会被遍历,类似 Get 操作。如果原型链上找不到 foo,foo 就会被直接添加到 myObject 上。🌱 ​这种情况下,如果foo存在原型链上层,赋值语句会行为会有所不同,下面我们会仔细介绍
  • 如果属性名 foo 既出现在 myObject 中也出现在 myObject 的 [[Prototype]] 链上层,那么就会发生屏蔽。myObject 中包含的 foo 属性会屏蔽原型链上层的所有 foo 属性,因为myObject.foo 总是会选择原型链中最底层的 foo 属性

🌳 屏蔽 比我们想象中的更加复杂,下面我们分析一下如果foo不直接存在于myObject中,而是存在于原型链上层myObject.foo='bar’的三种情况

  • 如果在 [[Prototype]] 链上层存在名为 foo 的普通数据访问属性并且没有被标记为只读(writable:false),那就会直接在 myObject 中添加一个名为 foo 的新属性,它是屏蔽属性
  • 如果在 [[Prototype]] 链上层存在 foo,但是它被标记为只读(writable:false),那么无法修改已有属性或者在 myObject 上创建屏蔽属性。如果运行在严格模式下,代码会抛出一个错误。否则,这条赋值语句会被忽略。总之,不会发生屏蔽
  • 如果在 [[Prototype]] 链上层存在 foo 并且它是一个 setter,那就一定会调用这个 setter。foo 不会被添加到(或者说屏蔽于)myObject,也不会重新定义 foo 这个 setter。

📝 小贴士:如果希望在第二种和第三种情况下也屏蔽 foo,那就不能使用 = 操作符来赋值,而是使用 Object.defineProperty(…)来向 myObject 添加 foo。

❗️ 以下代码会产生隐式屏蔽,需要注意

var anotherObject = {
a:2
};
var myObject = Object.create( anotherObject );
anotherObject.a; // 2

myObject.a; // 2

anotherObject.hasOwnProperty( "a" ); // true
myObject.hasOwnProperty( "a" ); // false

myObject.a++; // 隐式屏蔽!

anotherObject.a; // 2
myObject.a; // 3

myObject.hasOwnProperty( "a" ); // true

尽管 myObject.a++ 看起来应该(通过委托)查找并增加 anotherObject.a 属性,但是别忘了 ++ 操作相当于 myObject.a = myObject.a + 1。因此 ++ 操作首先会通过 [[Prototype]]查找属性 a 并从 anotherObject.a 获取当前属性值 2,然后给这个值加 1,接着将值 3 赋给 myObject 中新建的屏蔽属性 a

3 类

现在你可能会很好奇:为什么一个对象需要关联到另一个对象?这样做有什么好处?这个问题非常好,但是在回答之前我们首先要理解 [[Prototype]]“不是”什么。

JavaScript 和面向类的语言不同,它并没有类来作为对象的抽象模式或者说蓝图。JavaScript中只有对象

实际上,JavaScript才是真正应该被称为“面向对象”语言,因为它是少有的可以不通类,直接创建对象的语言。

在 JavaScript 中,类无法描述对象的行为,(因为根本就不存在类!)对象直接定义自己的行为。再说一遍,JavaScript 中只有对象。

3.1 “类”函数

在JavaScript中是没有类的,只有对象,所以可能会产生一种奇怪的行为,那就是 模仿类,我们会仔细分析这种方法

这种奇怪的类似类的行为利用函数的一种特殊特性:所有的函数默认都会拥有一个名为prototype的公有并且不可枚举的属性,它指向另一个对象

function Foo(){

}

Foo.prototype //{}

这个对象通常被称为Foo原型,因为我们通过名为 Foo.prototype 的属性引用来访问它。

🤔 那么,这个对象到底是什么?

🌴 这个对象是在调用new Foo()时创建的,最后会被关联到这个“Foo.prototype” 对象上

我们来验证一下:

function foo(){
	//...
}
var a=new Foo()

Object.getProtypeOf(a)=== Foo.prototype //true

调用new Foo()时会创建a(关于this那章),其中的第二步就是给a一个内部的[[Protype]] 链接,关联到Foo.prototype指向那个对象

🤔 接下来,我们来思考一下一些问题?

  • 面向类的语言有什么独特?
  • JavaScript模仿类的行为是什么?

🌴 理解如下:

在面向类的语言中,类可以被复制(或者说实例化)多次,就像用模具制作东西一样。之所以会这样是因为实例化(或者继承)一个类就意味着“把类的行为复制到物理对象中”,对于每一个新实例来说都会重复这个过程。

但是在 JavaScript 中,并没有类似的复制机制。你不能创建一个类的多个实例,只能创建多个对象,它们 [[Prototype]] 关联的是同一个对象。但是在默认情况下并不会进行复制,因此这些对象之间并不会完全失去联系,它们是互相关联的。

new Foo() 会生成一个新对象(我们称之为 a),这个新对象的内部链接 [[Prototype]] 关联的是 Foo.prototype 对象。

最后我们得到了两个对象,它们之间互相关联,就是这样。我们并没有初始化一个类,实际上我们并没有从“类”中复制任何行为到一个对象中,只是让两个对象互相关联。

🌴

3.2 构造函数与类的误解

function Foo(){

}
var a=new Foo()

到底是什么让我们认为Foo是一个类呢?或者说类与构造函数的误解是什么?

我觉得有两个地方会让我们产生误解:

  • 调用方式:我们看到了关键字 new,在面向类的语言中构造类实例时也会用到它。另一个原因是,看起来我们执行了类的构造函数方法,Foo() 的调用方式很像初始化类时类构造函数的调用方式。

  • 对象的constructor属性的指向:

    function Foo(){
    
    }
    Foo.prototype.constructor === Foo //true
    
    var a=new Foo()
    a.constructor === Foo //true
    

    Foo.prototype 默认(在代码中第一行声明时!)有一个公有并且不可枚举的属性 .constructor,这个属性引用的是对象关联的函数(本例中是 Foo)。此外,我们可以看到通过“构造函数”调用 new Foo() 创建的对象也有一个 .constructor 属性,指向

    “创建这个对象的函数”。

    ❗️ 但是实际上a本身并没有.constructor属性,虽然 a.constructor 确实指向 Foo 函数,但是这个属性并不是表示 a 由 Foo“构造”,🌱 稍后会解释的

3.3 构造函数是什么

上一节中的代码,我们使用new来调用它并且看到它构造了一个对象

实际上,Foo 和你程序中的其他函数没有任何区别。函数本身并不是构造函数,然而,当你在普通的函数调用前面加上 new 关键字之后,就会把这个函数调用变成一个“构造函数调用”。实际上,new 会劫持所有普通函数并用构造对象的形式来调用它。

例子如下:

function NothingSpecial() {
	console.log( "Don't mind me!" );
}
var a = new NothingSpecial();
// "Don't mind me!" 

a; // {}

NothingSpecial 只是一个普通的函数,但是使用 new 调用时,它就会构造一个对象并赋值给 a,这看起来像是 new 的一个副作用(无论如何都会构造一个对象)。这个调用是一个构造函数调用,但是 NothingSpecial 本身并不是一个构造函数。

换句话说,在 JavaScript 中对于“构造函数”最准确的解释是,所有带 new 的函数调用。

函数不是构造函数,但是当且仅当使用new时,函数调用会变成“构造函数调用”

3.4 构造函数的属性是什么

function Foo(name){
    this.name=name
}

Foo.prototype.myName=function(){
    return this.name
}

var a=new Foo("a")
var b=new Foo("b")

a.myName() //a
b.myName() //b

这段代码中有两个有意思值得思考的点:

  • this.name=name给每个对象(这是在关于this的博客说过,是关于this的指向绑定)都添加了.name属性,,有点像实例封装数据值
  • Foo.prototype.myName = … 可能个更有趣的技巧,它会给 Foo.prototype 对象添加一个属性(函数)。现在,a.myName() 可以正常工作,但是你可能会觉得很惊讶,这是什么原理呢?

在这段代码中,看起来似乎创建 a 和 b 时会把 Foo.prototype 对象复制到这两个对象中,然而事实并不是这样。

在本章开头介绍默认 [[Get]] 算法时我们介绍过 [[Prototype]] 链,以及当属性不直接存在于对象中时如何通过它来进行查找。

因此,在创建的过程中,a 和 b 的内部 [[Prototype]] 都会关联到 Foo.prototype 上。当 a和 b 中无法找到 myName 时,它会(通过委托,参见下一章)在 Foo.prototype 上找到

3.5 实例的constructor属性

回顾5.2.2中的一个问题:

❗️ 但是实际上a本身并没有.constructor属性,虽然 a.constructor 确实指向 Foo 函数,但是这个属性并不是表示 a 由 Foo“构造”,🌱 稍后会解释的

这个问题中,a.constructor === Foo为真,意味着a确实有指向Foo的.constructor属性,但是事实不是如此

🌳 实际上,.constructor引用同样被委托给了Foo.prototype,而Foo.prototype.constructor默认指向Foo。

把 .constructor 属性指向 Foo 看作是 a 对象由 Foo“构造”非常容易理解,但这只不过是一种虚假的安全感。a.constructor 只是通过默认的 [[Prototype]] 委托指向 Foo,这和“构造”毫无关系。相反,对于 .constructor 的错误理解很容易对你自己产生误导。

举例来说,Foo.prototype 的 .constructor 属性只是 Foo 函数在声明时的默认属性。如果你创建了一个新对象并替换了函数默认的 .prototype 对象引用,那么新对象并不会自动获得 .constructor 属性。

🤔 思考一下的代码:

![原型关系图](D:\学习专业资料\typora集合图片\你不知道的JavaScript笔记图片\原型关系图.jpg)function Foo(){ /* .. */ }

Foo.prototype={ /* .. */ }

var a1=new Foo()

a1.constructor === Foo //false
a1.constructor === Object //true

Object(…) 并没有“构造”a1,对吧?看起来应该是 Foo()“构造”了它。大部分开发者都认为是 Foo() 执行了构造工作,但是问题在于,如果你认为“constructor”表示“由……构造”的话,a1.constructor 应该是 Foo,但是它并不是 Foo !

到底怎么回事? a1 并没有 .constructor 属性,所以它会委托 [[Prototype]] 链上的 Foo.prototype。但是这个对象也没有 .constructor 属性(不过默认的 Foo.prototype 对象有这个属性!),所以它会继续委托,这次会委托给委托链顶端的 Object.prototype。这个对象有 .constructor 属性,指向内置的 Object(…) 函数。

5.3 (原型)继承

实际上,我们已经了解了通常被称作原型继承的机制,a可以继承Foo.prototype并访问Foo.prototype的myName()函数,但是我们之前只把继承看作是类是实例的关系,并没有把它看作是类是和类的关系:
原型描述

上面的那张关系图里,它不仅展示出对象(实例)a1 到 Foo.prototype 的委托关系,还展示出Bar.prototype 到 Foo.prototype 的委托关系,而后者和类继承很相似,只有箭头的方向不同。图中由下到上的箭头表明这是委托关联,不是复制操作。

下面这段代码使用的就是典型的“原型风格”

function Foo(name) {
	this.name = name;
}

Foo.prototype.myName = function() {
	return this.name;
};

function Bar(name,label) {
	Foo.call( this, name );
	this.label = label;
}

// 我们创建了一个新的 Bar.prototype 对象并关联到 Foo.prototype
Bar.prototype = Object.create( Foo.prototype );

// 注意!现在没有 Bar.prototype.constructor 了
// 如果你需要这个属性的话可能需要手动修复一下它
Bar.prototype.myLabel = function() {
	return this.label;
};

var a = new Bar( "a", "obj a" );

a.myName(); // "a"
a.myLabel(); // "obj a"

这段代码的核心部分就是语句 Bar.prototype = Object.create( Foo.prototype )。调用Object.create(…) 会凭空创建一个“新”对象并把新对象内部的 [[Prototype]] 关联到你指定的对象(本例中是 Foo.prototype)。

换句话说,这条语句的意思是:“创建一个新的 Bar.prototype 对象并把它关联到 Foo.prototype”。

声明 function Bar() { … } 时,和其他函数一样,Bar 会有一个 .prototype 关联到默认的对象,但是这个对象并不是我们想要的 Foo.prototype。因此我们创建了一个新对象并把它关联到我们希望的对象上,直接把原始的关联对象抛弃掉。

😄 如果有不明白为什么this指向a的话,可以查看上一篇博客
学习JavaScript的this的使用和原理这一篇就够了,超详细

❗️ 注意,下面这两种方式是替换原型常见的错误:

// 和你想要的机制不一样!
Bar.prototype = Foo.prototype;

// 基本上满足你的需求,但是可能会产生一些副作用 :
Bar.prototype = new Foo();

Bar.prototype = Foo.prototype 并不会创建一个关联到 Bar.prototype 的新对象,它只是让 Bar.prototype 直接引用 Foo.prototype 对象。因此当你执行类似Bar.prototype.myLabel = … 的赋值语句时会直接修改 Foo.prototype 对象本身。显然这不是你想要的结果,否则你根本不需要 Bar 对象,直接使用 Foo 就可以了,这样代码也会更简单一些。

Bar.prototype = new Foo() 的确会创建一个关联到 Bar.prototype 的新对象。但是它使用了 Foo(…) 的“构造函数调用”,如果函数 Foo 有一些副作用(比如写日志、修改状态、注册到其他对象、给 this 添加数据属性,等等)的话,就会影响到 Bar() 的“后代”,后果不堪设想。

因此,要创建一个合适的关联对象,我们必须使用 Object.create(…) 而不是使用具有副作用的 Foo(…)。这样做唯一的缺点就是需要创建一个新对象然后把旧对象抛弃掉,不能直接修改已有的默认对象。

4 对象关联

现在我们知道了,[[Prototype]] 机制就是存在于对象中的一个内部链接,它会引用其他对象。

通常来说,这个链接的作用是:如果在对象上没有找到需要的属性或者方法引用,引擎就会继续在 [[Prototype]] 关联的对象上进行查找。同理,如果在后者中也没有找到需要的引用就会继续查找它的 [[Prototype]],以此类推。这一系列对象的链接被称为“原型链”。

4.1 创建关联

我们可以使用Object.create()来创建对象之间的关联,非常简单和方便

var foo = {
something: function() {
console.log( "Tell me something good..." );
}
};
var bar = Object.create( foo );
bar.something(); // Tell me something good

Object.create(…) 会创建一个新对象(bar)并把它关联到我们指定的对象(foo),这样我们就可以充分发挥 [[Prototype]] 机制的威力(委托)并且避免不必要的麻烦(比如使用 new 的构造函数调用会生成 .prototype 和 .constructor 引用)。

📝 Object.create(null) 会 创 建 一 个 拥 有 空( 或 者 说 null)[[Prototype]]链接的对象,这个对象无法进行委托。这些特殊的空 [[Prototype]] 对象通常被称作“字典”,它们完全不会受到原型链的干扰,因此非常适合用来存储数据。

我们并不需要类来创建两个对象之间的关系,只需要通过委托来关联对象就足够了。而Object.create(…) 不包含任何“类的诡计”,所以它可以完美地创建我们想要的关联关系。

Object.create()的替代代码

Object.create(…) 是在 ES5 中新增的函数,所以在 ES5 之前的环境中(比如旧 IE)如果要支持这个功能的话就需要使用一段简单的代码片段,它部分实例了Object.create(…)的功能

if (!Object.create) {
	Object.create = function(o) {
		function F(){}
		F.prototype = o;
		return new F();
	};
}

这段 polyfill 代码使用了一个一次性函数 F,我们通过改写它的 .prototype 属性使其指向想要关联的对象,然后再使用 new F() 来构造一个新对象进行关联

4.2 关联关系的意义

看起来对象之间的关联关系是处理“缺失”属性或者方法时的一种备用选项。这个说法有点道理,但是我认为这并不是 [[Prototype]] 的本质

🤔 思考以下的代码:

var anotherObject = {
	cool: function() {
	console.log( "cool!" );
	}
};

var myObject = Object.create( anotherObject );

myObject.cool(); // "cool!"

由于存在 [[Prototype]] 机制,这段代码可以正常工作。但是如果你这样写只是为了让myObject 在无法处理属性或者方法时可以使用备用的 anotherObject,那么你的软件就会变得有点“神奇”,而且很难理解和维护。

这并不是说任何情况下都不应该选择备用这种设计模式,但是这在 JavaScript 中并不是很常见。所以如果你使用的是这种模式,那或许应当退后一步并重新思考一下这种模式是否合适。

在 ES6 中有一个被称为“代理”(Proxy)的高端功能,它实现的就是“方法无法找到”时的行为,如果有想了解的小伙伴,可以查看我的一篇博客
JavaScript的Proxy的使用和详情,还有代理的概念问题

当你给开发者设计软件时,假设要调用 myObject.cool(),如果 myObject 中不存在 cool()时这条语句也可以正常工作的话,那你的 API 设计就会变得很“神奇”,对于未来维护你软件的开发者来说这可能不太好理解。

⭐️ 但是你可以让你的 API 设计不那么“神奇”,同时仍然能发挥 [[Prototype]] 关联的威力:

var anotherObject = {
	cool: function() {
	console.log( "cool!" );
	}
};
var myObject = Object.create( anotherObject );

myObject.doCool = function() {
	this.cool(); // 内部委托!
};

myObject.doCool(); // "cool!"

这里我们调用的 myObject.doCool() 是实际存在于 myObject 中的,这可以让我们的 API 设计更加清晰(不那么“神奇”)。从内部来说,我们的实现遵循的是委托设计模式(参见下一章),通过 [[Prototype]] 委托到 anotherObject.cool()。

换句话说,内部委托比起直接委托可以让 API 接口设计更加清晰

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1199635.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

不使用 pip 安装 Python 包

在本文中,我们将学习如何在 Python 中安装没有 pip 的库。 我们还将学习如何使用 conda 命令在 Python 中安装包。 不使用 pip 命令安装 Python 库 在 Python 中,pip 命令是我们系统中安装开源库最常用的方法。 但是,除了 pip 命令之外&…

是谁为所欲为,将我的电脑控作己用?

在刚刚发完短篇小杂文《要找事做,我真怕被闲死》的投稿之后,笔者继续浏览社交网站的网页搜索...... 正看到《温州殡仪馆 》《温州动车723事故死亡高 》《 动车脱轨温州事件真正原因》《 浙江平阳县灭门惨案处理结果公布》《 温州厉秀珍死亡 》这一串又一…

C++ 中的内存分配 -- new 与 delete

c 常用的内存分配 分配释放类别是否可以重载mallocfreeC否newdeleteC 表达式(expressions)否operator new()operator delete()c 函数是operator new[]operator delete[]c 函数&#xff08;用于数组&#xff09;是allocator<T>::allocateallocator<T>::deallocatec …

java使用geotools导出shp文件

SHP格式是一种矢量数据格式&#xff0c;用于存储地理信息系统&#xff08;GIS&#xff09;数据。 SHP文件由一系列有序的文件组成&#xff0c;我们导出的shp文件包括.shp、.shx、.dbf、.prj以及.fix文件。 .shp&#xff08;shape&#xff09;文件&#xff1a;存储矢量地图数据&…

Ubuntu 22.04源码安装cmake 3.27.7

安装参考博客是《ubuntu安装cmake》和《Ubuntu 安装CMake》。 https://cmake.org/download是cmake官网下载的网址。 sudo wget -c https://github.com/Kitware/CMake/releases/download/v3.27.7/cmake-3.27.7.tar.gz可以下载源码&#xff0c;最后显示‘cmake-3.27.7.tar.gz’…

详解数据仓库之拉链表(原理、设计以及在Hive中的实现)

最近发现一本好书&#xff0c;读完感觉讲的非常好&#xff0c;首先安利给大家&#xff0c;国内第一本系统讲解数据血缘的书&#xff01;点赞&#xff01;近几天也会安排朋友圈点赞赠书活动(ง•̀_•́)ง 0x00 前言 本文将会谈一谈在数据仓库中拉链表相关的内容&#xff0c;包…

分类网络搭建示例

搭建CNN网络 本章我们来学习一下如何搭建网络&#xff0c;初始化方法&#xff0c;模型的保存&#xff0c;预训练模型的加载方法。本专栏需要搭建的是对分类性能的测试&#xff0c;所以这里我们只以VGG为例。 请注意&#xff0c;这里定义的只是一个简陋的版本&#xff0c;后续一…

基于猕猴感觉运动皮层的神经元Spike信号分析

公开数据集中文版详细描述参考前文&#xff1a;https://editor.csdn.net/md/?not_checkout1&spm1011.2124.3001.6192 目录 0. 公开数据集1. 神经元的raster和PSTH图1.1 Raster1.2 PSTH 2. 运动轨迹图 (center_out)3. 神经元的运动调制曲线 (tuning curve) 0. 公开数据集 …

Leetcode100120. 找出强数对的最大异或值 I

Every day a Leetcode 题目来源&#xff1a;100120. 找出强数对的最大异或值 I 解法1&#xff1a;模拟 枚举 2 遍数组 nums 的元素&#xff0c;更新最大异或值。 代码&#xff1a; /** lc appleetcode.cn id100120 langcpp** [100120] 找出强数对的最大异或值 I*/// lc c…

火爆进行中的抖音双11好物节,巨量引擎助5大行业商家开启爆单之路!

抖音双11好物节目前正在火热进行中&#xff0c;进入爆发期&#xff0c;各大商家“好招”频出&#xff0c;都想要实现高速增长。依托“人群、货品、流量”三大优势&#xff0c;巨量引擎一直都是商家生意增长的给力伙伴&#xff0c;在今年的抖音双11好物节&#xff0c;巨量引擎就…

SparkSQL之Catelog体系

按照SQL标准的解释&#xff0c;在SQL环境下Catalog和Schema都属于抽象概念。在关系数据库中&#xff0c;Catalog是一个宽泛的概念&#xff0c;通常可以理解为一个容器或数据库对象命名空间中的一个层次&#xff0c;主要用来解决命名冲突等问题。 在Spark SQL系统中&#xff0c;…

Django基础介绍及HTTP请求

文章目录 Django框架的介绍Django的安装 Django框架开发创建项目的指令Django项目的目录结构URL 介绍视图函数(view)Django 中的路由配置带有分组的路由和视图函数带有命名分组的路由和视图函数 HTTP协议的请求和响应HTTP 请求HTTP 响应GET方式传参POST传递参数form 表单的name…

泉峰控股发布业务白皮书, 释放中国芯片企业要发展成全球领先的信心与决心

近日,多元化芯片全球供应商泉峰控股发布了一份题为《致力于中国芯片产业自立自强》的业务白皮书。白皮书系统阐述了泉峰控股企业发展策略和业务规划,充分体现出中国芯片企业要在全球范围内实现技术突破、市场扩张的信心与决心。 白皮书首先分析了当前全球芯片产业的发展态势。在…

leetcode(力扣) 51. N 皇后 (回溯,纸老虎题)

文章目录 题目描述思路分析对于问题1对于问题2 完整代码 题目描述 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数…

业务出海之服务器探秘

这几年随着国内互联网市场的逐渐饱和&#xff0c;越来越多的公司加入到出海的行列&#xff0c;很多领域都取得了很不错的成就。虽然出海可以获得更加广阔的市场&#xff0c;但也需要面对很多之前在国内可能没有重视的一些问题。集中在海外服务器的选择维度上就有很大的变化。例…

rocksdb中测试工具Benchmark.sh用法(基准、性能测试)

1.首先要安装db_bench工具&#xff0c;这个工具在成功安装rocksdb之后就自动存在了&#xff0c;主要是在使用make命令之后就成功安装了&#xff0c;详情请见我之前的文章 2.确保成功安装db_bench之后&#xff0c;找到安装的rocksdb目录下面的tools文件夹&#xff0c;查看里面是…

怎么改变容易紧张的性格?

容易紧张的性格是比较通俗的说法&#xff0c;在艾森克人格测试中&#xff0c;容易紧张的性格就属于神经症人格&#xff0c;神经质不是神-经-病&#xff0c;而是一种人格特征&#xff0c;这种特征包括&#xff1a;敏感&#xff0c;情绪不稳定&#xff0c;易焦虑和紧张。有兴趣的…

(一)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB

一、七种算法&#xff08;DBO、LO、SWO、COA、LSO、KOA、GRO&#xff09;简介 1、蜣螂优化算法DBO 蜣螂优化算法&#xff08;Dung beetle optimizer&#xff0c;DBO&#xff09;由Jiankai Xue和Bo Shen于2022年提出&#xff0c;该算法主要受蜣螂的滚球、跳舞、觅食、偷窃和繁…

SpringBoot 监控

概述 SpringBoot自带监控功能Actuator&#xff0c;可以帮助实现对程序内部运行情况监控&#xff0c;比如监控状况、Bean加载情况、配置属性、日志信息等。 使用步骤 导入依赖坐标 <dependency><groupId>org.springframework.boot</groupId><artifactI…

HCIA-经典综合实验(一)

经典综合实验&#xff08;一&#xff09; 实验拓扑配置步骤第一步&#xff1a;配置二层VLAN第二步&#xff1a;配置IP地址第三步&#xff1a;配置DHCP服务第四步&#xff1a;配置路由协议OSPF第五步&#xff1a;配置ACLNATTelnet 配置验证测试PC1能不能telnet登录到R1测试所有P…