2023/1/14 js基础学习

news/2024/11/18 16:45:48/

1 js基础学习-基本数据类型+基本语法

请参考 https://blog.csdn.net/m0_48964052?type=blog
https://gitee.com/hongjilin/hongs-study-notes/blob/master/%E7%BC%96%E7%A8%8B_%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/HTML+CSS+JS%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0/JavaScript%E7%AC%94%E8%AE%B0/javaScript%E5%88%9D%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.md#%E7%AE%97%E6%95%B0%E8%BF%90%E7%AE%97%E7%AC%A6

  • String 字符串
  • Number 数值
  • Boolean 布尔值
  • Null 空值
  • Undefined 未定义
  • Object 对象
  • 其中基本数据类型:String Number Boolean Null Undefined

1 typeof运算符检查数据类型

    <!--    使用typeof运算符检查字符串时,会返回"string"-->var str = 'hello-word'console.log(typeof str); /*sout-> string*/var infinity_ = Infinity /*正无穷*/console.log(typeof infinity_); /*number*/

2 String字符串

字符串对于保存以文本形式表示的数据很有用。 一些最常用的字符串操作是检查他们的长度,使用 + 和 += 字符串操作符构建和连接它们 ,使用 indexOf() 方法检查子字符串的存在或者位置,或使用 substring()方法提取子字符串。
1 从字符串字面量将字符串创建为原始值

 const string1 = "A string primitive";

2 使用 String() 构造函数将字符串创建为对象

 const str = new String('hello zhaoshuai-lc');

3 JavaScript 区分 String 对象和原始字符串值:

字符串字面量是原始字符串:在要对原始字符串调用方法或者发生属性查找的上下文中,JavaScript将自动的包装原始字符串并调用方法或在包装对象上执行属性查找

   const strPrim = "foo"; // A literal is a string primitiveconst strPrim2 = String(1); // Coerced into the string primitive "1"const strPrim3 = String(true); // Coerced into the string primitive "true"const strObj = new String(strPrim); // String with new returns a string wrapper object.const strObj_ = new String('strPrim');console.log(typeof strPrim); // "string"console.log(typeof strPrim2); // "string"console.log(typeof strPrim3); // "string"console.log(typeof strObj); // "object"console.log(typeof strObj_); // "object"
eval()
eval是Javascript内置函数,用于计算字符串表达式的值。例如eval("2+3") 返回的是5const s1 = "2 + 2"; // creates a string primitive
const s2 = new String("2 + 2"); // creates a String object
console.log(eval(s1)); // returns the number 4
console.log(eval(s2)); // returns the string "2 + 2"String 对象始终可以使用 valueOf() 方法将其转换为它的原始值(字面量)。
const s2 = new String("2 + 2"); // creates a String object
console.log(eval(s2.valueOf())); // returns the number 4

3 Undefined 未定义

如果声明一个变量但是没有为变量赋值此时变量的值就是undefined 使用typeof检查一个Undefined类型的值时,会返回"undefined"

var obj
console.log(obj); /*undefined*/
console.log(typeof obj); /*undefined*/

4 Null 空值

空值专门用来表示为空的对象,Null类型的值只有一个 null 使用typeof检查一个Null类型的值时会返回"object"

var obj = null
console.log(typeof obj); /*object*/
console.log(obj); /*null*/

5 isNaN()

用来判断一个变量是否为非数字的类型,返回 true 或者 false, 首先会尝试将传入的值转化为Number

6 类型转换

<div id="类型转换">类型转换就是指将其他的数据类型,转换为String Number 或 Boolean<div>调用被转换数据的toString()方法例子:var a = 123;a = a.toString();注意:这个方法不适用于nullundefined由于这两个类型的数据中没有方法,所以调用toString()时会报错<div>var aconsole.log(a); /*undefined*/console.log(a.toString()); /*Cannot read properties of undefined (reading 'toString')*/console.log(typeof a); /*undefined*/</div><div>var a = nullconsole.log(a); /*null*/console.log(typeof a); /*object*/console.log(a.toString()); /*Cannot read properties of null (reading 'toString')*/</div>调用String()函数例子:var a = 123;a = String(a);原理:对于Number Boolean String都会调用他们的toString()方法来将其转换为字符串,对于null值,直接转换为字符串"null"。对于undefined直接转换为字符串"undefined"隐式的类型转换:为任意的数据类型 +""例子:var a = true;a = a + "";原理:和String()函数一样</div><div>转换为Number<div>方式一(强制类型转换):调用Number()函数例子:var s = "123";s = Number(s);转换的情况:字符串 -> 数字如果字符串是一个合法的数字,则直接转换为对应的数字如果字符串是一个非法的数字,则转换为NaN如果是一个空串或纯空格的字符串,则转换为0布尔值 -> 数字true 转换为1false 转换为0空值 -> 数字null 转换为0未定义 -> 数字undefined 转换为NaN</div><div>方式二(强制类型转换):调用parseInt()或parseFloat()这两个函数专门用来将一个字符串转换为数字的如果对非String使用parseInt()或parseFloat()例子:var a = "123.456px";a = parseInt(a); //123例子:var a = "123.456px";a = parseFloat(a); //123.456</div><div>方式三(隐式的类型转换):使用一元的+来进行隐式的类型转换例子:var a = "123";a = +a;console.log(a); /*123*/console.log(typeof a); /*number*/原理:和Number()函数一样</div></div><div>转换为布尔值<div>方式一(强制类型转换):使用Boolean()函数例子:var s = "false";s = Boolean(s); //true转换的情况字符串 -> 布尔除了空串其余全是true数值 -> 布尔除了0NaN其余的全是truenullundefined -> 布尔都是false对象 -> 布尔都是true</div><div>(隐式类型转换):为任意的数据类型做两次非运算,即可将其转换为布尔值例子:var a = "hello";a = !!a; //true</div></div>
</div>

7 运算符

<div id="运算符"><div id="typeof运算符">typeof运算符用来检查一个变量的数据类型</div><div id="算数运算符">做加法运算时,如果是两个字符串进行相加,则会做拼串操作,将两个字符连接为一个字符串。任何值和字符串做加法,都会先转换为字符串,然后再拼串</div><div id="一元运算符 +">正号,不会对值产生任何影响,但是可以将一个非数字转换为数字var a = trueconsole.log(+a) // 1var a = '11'console.log(+a) // 11</div><div id="一元运算符 -">负号,不会对值产生任何影响,但是可以将一个非数字转换为数字 然后对一个数字进行符号位取反var a = '11'console.log(-a) // 11console.log(typeof -a); // numbervar a = trueconsole.log(-a) // -1console.log(typeof -a); // number</div><div id="自增">自增可以使变量在原值的基础上自增1var a = 3console.log(a++); // 3var b =3console.log(++b) // 4</div><div id="逻辑运算符"><div id="!">非运算可以对一个布尔值进行取反,truefalse falsetrue当对非布尔值使用!时,会先将其转换为布尔值然后再取反我们可以利用!来将其他的数据类型转换为布尔值var a = 'niaho'console.log(!a); // falseconsole.log(!!a); // trueconsole.log(typeof !a); // Boolean</div><div id="&&">逻辑与&&只有两端的值都为true时,才会返回true。只要有一个false就会返回falsevar res = true && falseconsole.log(res); // false短路运算(逻辑中断)- 逻辑与语法: 表达式1 && 表达式2如果第一个表达式的值为真,则返回表达式2如果第一个表达式的值为假,则返回表达式1</div><div id="||">只有两端都是false时,才会返回false。只要有一个true,就会返回true。短路运算(逻辑中断)- 逻辑或规则:1.如果第一个值为true,则返回第一个值2.如果第一个值为false,则返回第二个值</div></div><div id="相等运算符">==相等,判断左右两个值是否相等,如果相等返回true,如果不等返回false相等会自动对两个值进行类型转换,如果对不同的类型进行比较,会将其转换为相同的类型然后再比较,转换后相等它也会返回truevar res = '11' == 11console.log(res); // true!=不等,判断左右两个值是否不等,如果不等则返回true,如果相等则返回false不等也会做自动的类型转换。var res = '11' != 11console.log(res); // false===全等,判断左右两个值是否全等,它和相等类似,只不过它不会进行自动的类型转换,如果两个值的类型不同,则直接返回falsevar res = '111' === 111console.log(res); // false!==不全等,和不等类似,但是它不会进行自动的类型转换,如果两个值的类型不同,它会直接返回true特殊的值:nullundefined由于undefined衍生自null,所以null == undefined 会返回true。但是 null === undefined 会返回falsevar res = null == undefinedconsole.log(res); // trueNaNNaN不与任何值相等,包括它自身 NaN == NaN //false</div>
</div>

2 js基础学习-数组的学习Array

数组是指一组数据的集合,其中的每个数据被称作元素,在数组中可以存放任意类型的元素。数组是一种将一组数据存储在单个变量名下的优雅方式。数组使用索引(index)来操作元素,索引指由0开始的整数。
https://gitee.com/hongjilin/hongs-study-notes/blob/master/%E7%BC%96%E7%A8%8B_%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/HTML+CSS+JS%E5%9F%BA%E7%A1%80%E7%AC%94%E8%AE%B0/JavaScript%E7%AC%94%E8%AE%B0/javaScript%E5%88%9D%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.md#%E6%95%B0%E7%BB%84array

// 创建数组
var arr = new Array()
var arr_ = []// 向数组中添加元素
// 数组对象[索引] = 值;
arr_[1] = 'hello'
console.log(arr_); // [ <1 empty item>, 'hello' ]
console.log(arr_.length); // 2// 创建数组时直接添加元素
var arr1_ = [1, 2, 3, 4, , 5, 'hello']
console.log(arr1_); // [ 1, 2, 3, 4, <1 empty item>, 5, 'hello' ]
console.log(arr1_.length); // 7var arr2_ = [null, undefined, 1, 'hello']
console.log(arr2_); // [ null, undefined, 1, 'hello' ]
console.log(arr2_.length); // 4/*
修改数组的长度
数组.length = 新长度
如果修改后的length大于原长度,则多出的部分会空出来
如果修改后的length小于原长度,则原数组中多出的元素会被删除
*/var arr3_ = [1, 2, 3, 4, 5]
arr3_.length = 2
console.log(arr3_); // [ 1, 2 ]
console.log(arr3_.length) // 2/**** 数组的方法push()    用来向数组的末尾添加一个或多个元素,并返回数组新的长度pop()    用来删除数组的最后一个元素,并返回被删除的元素unshift()    向数组的开头添加一个或多个元素,并返回数组的新的长度shift()    删除数组的开头的一个元素,并返回被删除的元素reverse()    可以用来反转一个数组,它会对原数组产生影响concat()    可以连接两个或多个数组,它不会影响原数组,而是新数组作为返回值返回*/var arr4_ = [1, 2, 3, 4, 5]
console.log(arr4_.push(100)); // 6
console.log(arr4_); // [ 1, 2, 3, 4, 5, 100 ]
console.log(arr4_.reverse()); // [ 100, 5, 4, 3, 2, 1 ]
console.log(arr4_); // [ 100, 5, 4, 3, 2, 1 ]
// ...// 数组遍历
var arr5_ = [1, 2, 3, 4, 5, 'hello', 'zhaoshuai-lc']
for (let item of arr5_) {console.log(item);
}
arr5_.forEach(item => console.log(item))

3 js基础学习-对象Object

对象是JS中的引用数据类型,对象是一种复合数据类型,在对象中可以保存多个不同数据类型的属性。使用typeof检查一个对象时,会返回object。

1 对象创建模式-Object构造函数模式

套路: 先创建空Object对象, 再动态添加属性/方法
适用场景: 起始时不确定对象内部数据
问题: 语句太多

<script>var p = new Object();p.name = 'zhaoshuai-lc'p.age = 27p.setName = function (name) {this.name = name}console.log(p);p.setName('zhaoshuai-la')console.log(p);</script>

在这里插入图片描述但是,引出一下问题:
在这里插入图片描述
为什么?箭头函数就出现了问题,这里涉及到的是箭头函数的问题:
对于箭头函数而言:this —> window
在这里插入图片描述
对于普通函数而言:this—>p
在这里插入图片描述

2 对象创建模式-对象字面量模式

套路: 使用{}创建对象, 同时指定属性/方法
适用场景: 起始时对象内部数据是确定的
问题: 如果创建多个对象, 有重复代码

<script>var p = {name: 'zhaoshuai-lc',age: 27,sex: 'male'}console.log(p);
</script>

在这里插入图片描述

3 对象创建模式-自定义构造函数模式

套路: 自定义构造函数, 通过new创建对象
适用场景: 需要创建多个类型确定的对象
问题: 每个对象都有相同的数据, 浪费内存
在这里插入图片描述

4 对象创建模式-构造函数+原型的组合模式

构造函数+原型的组合模式–>最好用这个写法
套路: 自定义构造函数, 属性在函数中初始化, 方法添加到原型上
适用场景: 需要创建多个类型确定的对象
放在原型上可以节省空间(只需要加载一遍方法)

在这里插入图片描述

4 继承模式-原型链继承

子类型的原型为父类型的一个实例对象

<script><!--    父类型-->function Supper() {this.supPro = 'Supper property'}Supper.prototype.showSupperProp = function () {console.log(this.supPro);}//    定义子类型function Sub() {this.subPro = 'Sub property'}Sub.prototype.showSubProp = function () {console.log(this.subPro);}var sub = new Sub();// 子类调用父类的方法,此时是有问题的sub.showSupperProp();
</script>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
引出一个问题:sub.constructor 竟然指向的是Supper的构造函数
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
解决方案:constructor 我们称为构造函数,因为它指回构造函数本身
在这里插入图片描述

5 继承模式-构造函数补充

6 继承模式-借用构造函数继承(假的)

7 继承模式-组合继承

基本数据类型和引用数据类型

基本数据类型 String Number Boolean Null Undefined
引用数据类型 Object
基本数据类型的数据,变量是直接保存的它的值,变量与变量之间是互相独立的,修改一个变量不会影响其他的变量。
引用数据类型的数据,变量是保存的对象的引用(内存地址),如果多个变量指向的是同一个对象,此时修改一个变量的属性,会影响其他的变量。
比较两个变量时,对于基本数据类型,比较的就是值,对于引用数据类型比较的是地址,地址相同才相同。

4 js基础学习-函数(Function)

函数也是一个对象,也具有普通对象的功能,函数中可以封装一些代码,在需要的时候可以去调用函数来执行这些代码,使用typeof检查一个函数时会返回function。

// 函数的声明
function func(name, age, sex) {console.log(name, age, sex);
}// 函数表达式
var func_ = function (name, age, sex) {console.log(name, age, sex);
}
// 函数的调用-当我们调用函数时,函数中封装的代码会按照编写的顺序执行
func('zhaoshuai-lc', 26, 'male');// 立即执行函数-函数定义完,立即被调用,立即执行函数往往只会执行一次
(function (name, age) {console.log(name, age)
})('zhaoshuai-la', 27);/*
调用函数时JS解析器不会检查实参的类型和个数,可以传递任意数据类型的值:如果实参的数量大于形参,多余实参将不会赋值;如果实参的数量小于形参,则没有对应实参的形参将会赋值undefined;
*//*
返回值,就是函数执行的结果:语法:return 值;该值就会成为函数的返回值,可以通过一个变量来接收返回值,return后边的代码都不会执行,一旦执行到return语句时,函数将会立刻退出。return后可以跟任意类型的值,可以是基本数据类型,也可以是一个对象。如果return后不跟值,或者是不写return则函数默认返回undefined。break、continue和returnbreak-退出循环continue-跳过当次循环return-退出函数
*//*
参数,函数的实参也可以是任意的数据类型。
*/// 函数的属性和方法
/*
call() && apply()1 这两个方法都是函数对象的方法需要通过函数对象来调用2 通过两个方法可以直接调用函数,并且可以通过第一个实参来指定函数中this3 不同的是call是直接传递函数的实参, 而apply需要将实参封装到一个数组中传递argumentsarguments和this类似,都是函数中的隐含的参数arguments是一个类数组元素,它用来封装函数执行过程中的实参所以即使不定义形参,也可以通过arguments来使用实参arguments中有一个属性callee表示当前执行的函数对象this是函数的上下文对象,根据函数的调用方式不同会执向不同的对象1.以函数的形式调用时[独立调用],this是window2.以对象.方法的形式调用时[谁调用就指向谁],this是调用方法的对象3.以构造函数的形式调用时,this是新建的那个对象4.使用call和apply调用时,this是指定的那个对象5.在全局作用域中this代表window
*/// 作用域 - 一个变量的作用范围
/*
全局作用域:1 直接在script标签中编写的代码都运行在全局作用域中2 全局作用域在打开页面时创建,在页面关闭时销毁3 全局作用域中有一个全局对象window,window对象由浏览器提供,可以在页面中直接使用,它代表的是整个的浏览器的窗口。4 在全局作用域中创建的变量都会作为window对象的属性保存5 在全局作用域中创建的函数都会作为window对象的方法保存6 在全局作用域中创建的变量和函数可以在页面的任意位置访问7 在函数作用域中也可以访问到全局作用域的变量8 尽量不要在全局中创建变量函数作用域:1 函数作用域是函数执行时创建的作用域,每次调用函数都会创建一个新的函数作用域2 函数作用域在函数执行时创建,在函数执行结束时销毁3 在函数作用域中创建的变量,不能在全局中访问4 当在函数作用域中使用一个变量时,它会先在自身作用域中寻找,如果找到了则直接使用,如果没有找到则到上一级作用域中寻找,如果找到了则使用,找不到则继续向上找 ,,,
*//*
变量的声明提前:
1 在全局作用域中,使用var关键字声明的变量会在所有的代码执行之前被声明,但是不会赋值所以我们可以在变量声明前使用变量。但是不使用var关键字声明的变量不会被声明提前。
2 在函数作用域中,也具有该特性,使用var关键字声明的变量会在函数所有的代码执行前被声明.3 如果没有使用var关键字声明变量,则变量会变成全局变量<script>function fun() {a = 100}fun()console.log(a) // 100</script>
*//*
函数的声明提前
在全局作用域中,使用函数声明创建的函数 function fun(){}, 会在所有的代码执行之前被创建,也就是我们可以在函数声明前去调用函数,
但是使用函数表达式 var fun = function(){} 创建的函数没有该特性
在函数作用域中,使用函数声明创建的函数,会在所有的函数中的代码执行之前就被创建好了。
*//*
构造函数是专门用来创建对象的函数1 一个构造函数我们也可以称为一个类2 通过一个构造函数创建的对象,我们称该对象是这个构造函数的实例3 通过同一个构造函数创建的对象,我们称为类对象4 构造函数就是一个普通的函数,只是他的调用方式不同,如果直接调用,它就是一个普通函数如果使用new来调用,则它就是一个构造函数*/
function Person(name, age, gender) {console.log('this - ', this)this.name = name;this.age = age;this.gender = gender;this.sayHi = () => {console.log('hello-zhaoshuai-lc')}
}var person = new Person('zhaoshuai-lc', 22, 'male');
// console.log('this - ', this) //  Person {}/*
构造函数的执行流程:1.创建一个新的对象2.将新的对象作为函数的上下文对象(this)3.执行函数中的代码4.将新建的对象返回*//*
instanceof 用来检查一个对象是否是一个类的实例
语法:对象 instanceof 构造函数如果该对象时构造函数的实例,则返回true,否则返回falseconsole.log('person instanceof Person - ', person instanceof Person)// person instanceof Person -  true
Object是所有对象的祖先,所以任何对象和Object做instanceof都会返回true*/Person('zhaoshuai-lc', 22, 'male');
// console.log('this - ', this) //  Object

5 原型(prototype)

/*** 创建一个函数以后,解析器都会默认在函数中添加 - prototype* prototype属性指向的是一个对象,这个对象我们称为原型对象。* 当函数作为构造函数使用,它所创建的对象中都会有一个隐含的属性执行该原型对象。* 这个隐含的属性可以通过对象.__proto__来访问*/function Person(name, age, sex) {this.name = namethis.age = agethis.sex = sexthis.sayHi = () => {console.log('sayHi zhaoshuai-lc')}
}var person = new Person('zhaoshuai-lc', 28, 'male');
console.log(person.__proto__);/**原型对象就相当于一个公共的区域,凡是通过同一个构造函数创建的对象他们通常都可以访问到相同的原型对象。我们可以将对象中共有的属性和方法统一添加到原型对象中, 这样我们只需要添加一次,就可以使所有的对象都可以使用。当我们去访问对象的一个属性或调用对象的一个方法时,它会先自身中寻找,如果在自身中找到了,则直接使用。如果没有找到,则去原型对象中寻找,如果找到了则使用。如果没有找到,则去原型的原型中寻找,依此类推。直到找到Object的原型为止,Object的原型的原型为null,如果依然没有找到则返回undefined。hasOwnProperty()这个方法可以用来检查对象自身中是否含有某个属性语法:对象.hasOwnProperty("属性名")*/
<script>function Person(name, age, sex) {this.name = namethis.age = agethis.sex = sexthis.sayHi = () => {console.log('sayHi zhaoshuai-lc')}}var person = new Person('zhaoshuai-lc', 28, 'male');console.log('person.__proto__ = ', person.__proto__);console.log('person.hasOwnProperty(\'name\') = ', person.hasOwnProperty('name'));// person.hasOwnProperty('name') =  true
</script>

在这里插入图片描述


http://www.ppmy.cn/news/12815.html

相关文章

云原生|kubernetes|2022年底cks真题解析(1-10)

前言&#xff1a; cka和cks认证真的比较恶心&#xff0c;他们的那个PSI Bridge Secure Browser真的非常卡。 吐槽完毕&#xff0c;不废话&#xff0c;直接上真题解析。 CKS总共是16道题&#xff0c;题目顺序是打乱的&#xff0c;由于认证系统非常卡&#xff0c;因此&#xf…

Pycharm入门搭建Django 项目

一、环境准备 1、pycharm版本 2、python版本 二、创建项目 击左上角的 File -> New Project 点击Create创建完成之后页面等待下载环境 查看Django的版本 python -m django --version 启动项目 python manage.py runserver 三、后记 在启动 Django 项目的时候我发现控制台…

springcloud alibaba -- seata原理和使用

文章目录一、认识Seata1.1 Seata 是什么?1.2 了解AT、TCC、SAGA事务模式?AT 模式前提整体机制如何实现写隔离如何实现读隔离TCC 模式Saga 模式Saga 模式适用场景Saga 模式优势Saga 模式缺点二、Seata安装2.1 下载2.2 创建所需数据表2.2.1 创建 分支表、全局表、锁表2.2.2 创建…

HNUCM-蓝桥杯PythonB组寒假练习2

问题 A: 选房子题目描述栋栋和李剑已经大四了&#xff0c;想要出去找房子住。他们一共看中了n套房子。其中第i套房子已经住了ai个人了&#xff0c;它最多能住bi个人。栋栋和李剑想要住在一起&#xff0c;那么请问他们有几套可以选择的房子&#xff1f;输入输入的第一行为一个正…

C++11 std::function 基础用法

std::function是C11标准库中提供的一种可调用对象的通用类型&#xff0c;它可以存储任意可调用对象&#xff0c;如函数指针&#xff0c;函数对象&#xff0c;成员函数指针和lambda表达式。std::function类模板是一个类似于函数指针的类型&#xff0c;但它是可以处理任意可调用对…

内网穿透的概念及解决方案

1.什么是内网穿透 在外网的web请求可以转发到内网的本地服务 2.什么是内网&#xff1f;什么是外网&#xff1f; 内网(也叫局域网(Local Area Network&#xff0c;LAN))是在一个局部的地理范围内&#xff0c;一般可以是是几米内(比如家庭内网)&#xff0c;也可以是方圆几千米…

基于 TensorFlow 的深度学习图像识别模型的自动化测试(完整代码+数据)

任务目标: 针对深度学习图像识别模型的自动化测试框架,设计并实现一个 Python 实现的基于 TensorFlow 的深度学习图像识别模型的自动化测试方法,采用特定的方 式,根据提供的训练数据集和待测数据集,由待测数据集尽量生成使得模型出错但 是和原始数据“相似度”高的测试数据…

蓝桥云课 并查集练习题

蓝桥幼儿园 题目描述 蓝桥幼儿园的学生是如此的天真无邪&#xff0c;以至于对他们来说&#xff0c;朋友的朋友就是自己的朋友。 小明是蓝桥幼儿园的老师&#xff0c;这天他决定为学生们举办一个交友活动&#xff0c;活动规则如下&#xff1a; 小明会用红绳连接两名学生&…