当前位置: 首页 > news >正文

day15JS-es6的基础语法

 1. 严格模式

1.1 严格模式的使用方法

使用方法1:"use strict"; 开启严格模式。

使用方法2:<script type="moaule"></script> 当设置script标签为模块化时,自动启用严格模式。

 1.2 严格模式的限制

1. 要求变量不能重名

//报错
"use strict";
var a=2;
var a=4;

 2. 函数中的参数不能同名

//报错
"use strict";
function fn(a, a) {};
fn(1, 2);

 3. 在不声明变量的情况下使用变量,是不允许的

"use strict";
x = 3.14;  // 会引发错误(x 未定义)

 4. 对象也是变量,在不声明对象的情况下使用对象也是不允许的

"use strict";
x = { p1: 10, p2: 20 };      // 这将引发错误

 

 5. 删除变量(或对象)是不允许的

"use strict";
var x = 3.14;
delete x; // 这将引发错误

 6. 删除函数是不允许的

"use strict";
function x(p1, p2) { };
delete x;// 这将引发错误

7. 不能使用with

 with的注意事项!!!

  • with在设置某个对象下的属性时,必须保证这个属性是存在的不能新建,就可以修改
  • 如果不存在,意味着with定义了一个全局的变量

 with的使用案例:

        // 不能使用withvar div = document.querySelector("div");div.style.width = "50px";div.style.height = "50px";with (div.style) {width = "50px";height = "50px"backgroundColor = "red"}

 案例:

        var o = {a: 1,b: {c: 3,d: 4}}with (o.b) {c = 5;d = 10;e = 20;}console.log(o);console.log(e);

 

8.  建议大家使用eval (反射),eval 的作用是将字符串反射为js语句

console.log("3+4");//"3+4"
console.log(eval("3+4"));//7

 

9. 八进制数值文本不允许的

"use strict";
var x = 010; // 这将引发错误

10.  使用转义字符不允许的

"use strict";
var x = \010;// 这将引发错误

11.写入只读属性不允许的

"use strict";
var obj = {};
Object.defineProperty(obj, "x", {value:0, writable:false});obj.x = 3.14;// 这将引发错误

12.写入只能获取的属性不允许的

"use strict";
var obj = {get x() {return 0} };obj.x = 3.14;// 这将引发错误

13. 删除不可删除的属性不允许的

"use strict";
delete Object.prototype; // 这将引发错误

14. 字符串 "eval" 和 "arguments" 不可用作变量

"use strict";
var eval = 3.14;// 这将引发错误
"use strict";
var arguments = 3.14;// 这将引发错误

 1.3 在严格模式下this的指向

 查看day10JS-this的使用情况。

1.4 执行函数的方式有哪些?

  1. 函数名();  ---> 例如:fn();
  2. new 函数名(); ---> 例如:new fn();
  3. 函数名.call(); ---> 例如: fn.call()
  4. 函数名.apply(); ---> 例如: fn.apply();

1.5 call()方法 /apply()方法

1. call(); 方法 /apply(); 方法 传入方法第一个参数Object对象时this 指向的就是那个传入的Object对象。因为这两个方法在执行函数会将函数中 this 指向为call() /apply()方法中的第一个参数。这两个方法的作用就是改变this的指向开不开启严格模式都不会影响this的指向

function fn() {console.log(this);
}
let object = { a: 1 };
fn.call(object);
fn.apply(object);

 注意特殊情况!!!

非严格模式下

2. 传入call()方法第一个参数undefined或者是nullthis指向的是window

3. 传入call()方法第一个参数基本数据类型,会将传入的内容转换为第一个参数的对应的对象类型this指向的是该基本数据类型的对象

严格模式下

this将指向参数传入的内容

 非严格模式下:

// 非严格模式 : window
function fn(a, b) {console.log(this, a, b); 
}
fn.call(undefined, 1, 2)//window 1 2
fn.call(null, 1, 2)//window 1 2//非严格模式下:会将传入的内容转换为对应的对象类型
fn.call(1)//Number undefined undefined
fn.call("a")//String undefined undefined
fn.call(true)//Boolean undefined undefined

严格模式下:

//严格模式 : this将指向参数传入的内容
"use strict";
function fn(a, b) {console.log(this, a, b); 
}
fn.call(undefined, 1, 2)//undefined 1 2
fn.call(null, 1, 2)//null 1 2fn.call(1)//1 undefined undefined
fn.call("a")//a undefined undefined
fn.call(true)//true undefined undefined

1.6 call()方法 /apply()方法的区别

call()方法 :call传参一个个传。例如: fn.call(object,1,2);

apply()方法 :apply传参传入数组。例如:fn.apply(object,[1,2]);

1.7 callee属性与caller属性

1. 在严格模式下不允许使用calleecaller。非严格模式下可以使用。

callee是arguments的一个属性,指向其函数自身

2. caller返回一个函数的引用这个函数里面调用了当前使用caller属性的函数

使用这个属性要注意:

  1. 这个属性只有当函数在执行时才有用。
  2. 如果在javascript程序中,函数是由顶层调用的,则返回null

非严格模式的案例: 

//非严格模式
function fn() {console.log(arguments.callee);//就是当前函数
}
fn();

非严格模式的案例:  callee的作用就是可以删除当前函数

document.addEventListener("click", function () {document.removeEventListener("click", arguments.callee)
})

非严格模式的案例: : caller

        function fn1() {console.log(fn1.caller);//在全局中执行fn1,上下文环境的函数就是nullfn2();}function fn2() {console.log(fn2.caller);//执行当前函数上下文环境中函数fn1}fn1();

2. 解构赋值

2.1 数组的补充知识

1. 数组的最后一个元素空元素,那么它不作为数组的元素length的长度不加上空元素的长度。

2. 空元素不等于undefined

补充知识1的案例:

//补充知识1的案例:
var arr = [1, 2,];
console.log(arr);
console.log(arr.length);//2

补充知识2的案例: 

var arr = [1, 2, , 3, undefined, 4];
console.log(arr.length);//6

注意!!!

1. forEach遍历数组不会遍历数组中的空元素,但会遍历数组中的undefined

3. for循环遍历数组会遍历数组中的空元素,遍历结果空元素是undefined也会遍历数组中的undefined

      var arr=[1,2,,3,,4];arr.forEach(function(item){console.log(item);//1 2 3 4})
--------------------------------------var arr=[1,2,,3,,4];for(var i=0;i<arr.length;i++){console.log(arr[i]);//1 2 undefined 3 undefined 4}
-----------------------------------------var arr=[1,2,,3,undefined,4];arr.forEach(function(item){console.log(item);//1 2 3 undefined 4})
------------------------------------------var arr=[1,2,,3,undefined,4];for(var i=0;i<arr.length;i++){console.log(arr[i]);//1 2 undefined 3 undefined 4}

如何使用for循环去除数组中的空元素。使用in来判断这个属性是否是这个对象的属性。

      var arr=[1,2,,3,undefined,4];for(var i=0;i<arr.length;i++){if(i in arr){console.log(arr[i]);//1 2 3 undefined 4}}

2.2 解构赋值的用途与使用方法

解构赋值主要用于数组解构对象解构数组解构按位解构, 对象解构按属性名解构

数组解构的使用方法:var/let [变量名1,变量名2, ...] = [值1,值2, ...];

对象解构的使用方法:var/let {变量名1,变量名2, ...} = {值1,值2, ...};

 2.3 数组解构的案例

普通数组解构:

数组解构按位解构
let [a,b]=[1,2];//a=1,b=2
-------------------------
交换案例:
let a=1;
let b=2;
[b,a]=[a,b];
console.log(a,b);//a=1,b=1
-------------------------
let [a,b]=[1,2,3];
console.log(a,b);//a=1,b=2
-------------------------
let [a,b]=[1];
console.log(a,b);//a=1,b=undefined
-------------------------
// 给b设置初始值,如果b没有得到解构值,则是0
let [a,b=0]=[1];
console.log(a,b);//a=1,b=0

函数数组解构:

      function fn([a,b=0]){console.log(a,b);//a=1,b=0}fn([1]);-------------------------------------//这种赋值方式是由上面而得到的function fn(a,b=0){}fn(1);
---------------------------------------//这个解构赋值是 fn1=fn11这个函数,fn2=fn22这个函数,let [fn1,fn2]=[function(){//取个别名fn11console.log("fn11");},function(){//取个别名fn22console.log("fn22");}]fn1();//fn11fn2();//fn22

2.4 对象解构案例

对象解构按属性名解构,该属性名不存在那就是undefined

普通对象解构:

      // 对象解构// 对象解构按属性名解构,该属性名不存在那就是undefinedlet {a,c}={a:1,b:2};console.log(a,c);//a=1,c=undefined
---------------------------------------------//b有没有值?b没有值,因为b被重新二次分配给了{c,d},b不存在。//b不存在就是未定义,会报错。但是a、c、d是存在的let {a,b:{c,d}}={a:1,b:{c:3,d:4}};console.log(a,b);//报错//如果就想要b怎么办,那就不解构blet {a,b}={a:1,b:{c:3,d:4}}console.log(a,b);//a=1,b={c:3,d:4}//如果a,b,c,d都想要怎么办,b一次不解构,一次解构let {a,b:{c,d},b}={a:1,b:{c:3,d:4}};console.log(a,b,c,d);//a=1,b={c:3,d:4},c=3,d=4
---------------------------------------------// 可以设置默认值let {a,b=0}={a:1}console.log(a,b);//a=1,b=0

函数对象解构:在使用解构赋值作为函数参数传参,可以忽略函数参数先后顺序。

      // 在使用解构赋值作为函数参数传参,可以忽略函数参数先后顺序function fn({a,b,c=2}){console.log(a,b,c);//a=1,b=2,c=2}fn({a:1,b:2});

注意!!!

函数的参数问题

函数传参的顺序必须严格按照这个顺序来写:必填参数,默认值参数,可选参数,剩余参数。

例如:function fn(a , b=2 , c , ...arg){ };

 对象解构作为函数参数使用,可以避免参数传递的先后顺序问题。

对象解构中有相同属性名需要起别名,别名给入这个变量新的名字。

      function fn({num,bool,fn}) {//这种不牵扯到必填的问题console.log(num,bool,fn);//num=1,bool=undefineed,fn=一个函数}fn({num:1,fn:function(){}});
-------------------------------------------//如果已经有了a这个属性名,我就给它取一个别名。let {a,b:{a:a1}}={a:1,b:{a:2}};console.log(a,a1);//a=1,a1=2
--------------------------------------------// 如果已经有了a这个属性名,我就给它取一个别名并且赋初始值//如果没有匹配到就使用初始值。let {a,b:{a:a1=0}}={a:1,b:{}};console.log(a,a1);//a=1,a1=0
----------------------------------------------//如果后面没有b,那么b是有初始值为{a:3}let {a,b:{a:a1=0}={a:3}}={a:1};console.log(a,a1);//a=1,a1=3
-----------------------------------------------//如果后面有b,所以不取初始值{a:3}//但是b是一个空对象,b里面没有a1,所以a1取初始值0let {a,b:{a:a1=0}={a:3}}={a:1,b:{}};console.log(a,a1);//a=1,a1=0
-------------------------------------------------let {a,b:{a:a1=0}={a:3}}={a:1,b:{a:10}};console.log(a,a1);//a=1,a1=10
------------------------------------------------------function fn({ a, b: { a: a1 = 0 } = { a: 3 } } = { a: 1, b: {} }) {console.log(a, a1);}//没有传参,使用默认值fn();//a=1,a1=0// {a,b:{a:a1=0}={a:3}}是形参,{ a: 1 }是实参// {a,b:{a:a1=0}={a:3}}={a:1}// 后面没有b,所以取初始值{a:3}fn({ a: 1 });//a=1,a1=3// {a,b:{a:a1=0}={a:3}}={a:1,b:{a:10}}fn({ a: 1, b: { a: 10 } });//a=1,a1=10

3. Set集合与Map映射

3.1 Array与Object简介

        Array:是紧密结构,使用下标存储数据存储的数据可以重复,无序存储(不会自动排序)可以手动排序,不关心key只关心存储的值。查询速度慢、添加删除速度慢 。

        Object : 是松散结构,以键值对形式(key->value)存储存储key不能重复,value值是可以重复无序存储并且不能排序,查找速度快,可以直接根据key找到对应value值,添加删除速度快。无法获取对象的数据长度key要求必须是字符串或者symbol,如惠不是就会自动隐式转换为字符串 。

3.2 Set集合与Map映射简介

        Set集合:松散结构,存储的是任何类型的任意值没有key只有value的集合数据不能重复(唯一)不能排序插入,删除速度快,可以得到集合中数据的长度,可以遍历,查找速度快 。

        Map映射:松散结构键值对形式存储任何值数据类型都可以作为键(key)或值(value),键(key)名不能重复。Map的参数只能放迭代器使用解构赋值。查找和添加删除速度快,不能排序可以获取到数据存储的长度

3.3  WeakSet集合与WeakMap映射简介

 WeakSet:弱引用集合。

 WeakMap:弱引用映射。

3.4 迭代器

  1. HTMLCollection
  2. NodeList
  3. arguments
  4. Array
  5. Set本身也是迭代器

4. Set集合

4.1 Set集合的属性和方法

let s = new Set([1,2,3,4])
console.log(s);

  1. add() : 添加。如果添加相同的value值不会重复添加的
  2. delete() : 删除。
  3. has() :判断这个值在集合中是否存在,返回值是布尔值。
  4. clear() : 清除集合中所有的数据。
  5. size属性:Set集合没有length,但可以使用.size属性查看Set集合中数据的多少。
        let s=new Set([1,2,3,4]);// set的增加方法不重复value值,使用添加s.add(5);s.add(5);console.log(s);//Set(5) {1, 2, 3, 4, 5}s.delete(5)//删除console.log(s);//Set(4) {1, 2, 3, 4}//判断这个值在集合中是否存在,得到布尔值console.log(s.has(5));//false//清除所有数据s.clear();console.log(s.clear());//undefinedconsole.log(s);//Set(0) {}//数据的多少,没有length,只能通过size获取console.log(s.size);//0

Set集合的遍历方法:

1.  forEach

2. for of

        let s=new Set([1,2,3,4]);//方法一:s.forEach(function(value){console.log(value);//1 2 3 4 })//方法二:for(var value of s){console.log(value);//1 2 3 4 }

4.2 Set集合的使用场景

4.2.1 去重

var arr=[1,2,3,1,2,3,4,5,7,6,4,3,2,4,6,5,7];
//把数组arr放到Set集合中,Set集合去重,在使用数组的from()方法把Set集合转成数组
var arr1=Array.from(new Set(arr));
console.log(arr);//[1, 2, 3, 1, 2, 3, 4, 5, 7, 6, 4, 3, 2, 4, 6, 5, 7]
console.log(arr1);//[1, 2, 3, 4, 5, 7, 6]
console.log(arr1===arr);//false

使用Set去重有缺点就是引用地址会改变,去重过后的数组与原来的数组不是同一个。所以去重看实际开发的要求来使用。

4.2.2 减少查找

 

6.  WeakSet集合

6.1 强引用关系与弱引用关系的概念

1. undefined与null的区别:undefined只是开辟了空间没有赋值。null的作用就是清除引用关系,方便垃圾回收机制回收。

2. 强引用关系:先将对象的引用地址赋值给数组,在将对象设置为null,引用列表就清除该对象的引用,但是有数组存储着它的引用地址,垃圾回收车不会清除这个数据数组中存储的对象引用地址强引用存储

强引用关系的案例:

        // 强引用关系var o = { a: 1 };let s = new Set();s.add(o);o = null;console.log(s);

3. 弱引用关系:先将对象的引用地址赋值给数组,在将对象设置为null,但是数组中的引用地址也跟着改变,变成了null除了当前WeakSet没有变量在引用这个地址。会清除当前列表中的数据,这种就弱引用存储。WeakSet集合与WeakMap映射是弱引用地址,其它都是强引用地址。

弱引用关系的案例:

        // 弱引用关系var o = { a: 1 };let s = new WeakSet();s.add(o);o = null;console.log(s);

 代码的运行结果有两种:一种是及时被垃圾回收机制清除了,一种是还没有被垃圾回收机制清除。

原因是:垃圾回收机制是过了一定的时间才启动,垃圾回收机制启动时间是不可控制的。

6.2  WeakSet集合的方法

 WeakSet的概念

WeakSet 结构与 Set 类似,也是不重复的值的集合。但是,它与 Set 有两个区别。

1. WeakSet 是一个个构造函数。可以接受数组类似数组的对象作为参数。该数组的所有成员都会自动成为 WeakSet 的实例对象的成员。

2. WeakSet 的成员只能是对象而不能是其他类型的值

3. WeakSet 中的对象都是弱作用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑对象是否还存在于 WeakSet 之中。

 WeakSet的属性和方法:

  1. add() : 添加。
  2. delete() : 删除。
  3. has() :判断这个值在集合中是否存在,返回值是布尔值。

 WeakSet不能遍历。WeakSet 没有 size 属性,没有办法遍历其成员。

7. Map映射

7.1 Map映射的属性与方法

        // Map 映射let m = new Map();// 设置key是a,value是1m.set("a", 1);//设置key是true,value是falsem.set(true, false);var o = { a: 1 };var o1 = { a: 2 };//设置key是o,value是o1m.set(o, o1);console.log(m);

  1. set() :设置与指定的键 key 关联的值,并返回 Map 对象。
  2. get() :根据key可以获取到对应的value值。
  3. keys() :获取Map中所以的key。

  4. values() :获取Map中所以的value值。

  5. delete() :删除map中对应key的value值。
  6. clear() :遍历删除Map 对象中所有的键值对。
  7. has() :判断这个值在集合中是否存在,返回值是布尔值。
  8. entries() :获取map的迭代器。

  9. size属性:查看Map集合中数据的数量。
        // Map 映射let m = new Map();m.set("a", 1);m.set(true, false);var o = { a: 1 };var o1 = { a: 2 };m.set(o, o1);console.log(m);// 根据key可以获取到对应的valueconsole.log(m.get("a"));console.log(m.get(o));// 删除map中对应key的valuem.delete(o);// 清空m.clear();// 判断key是否存在console.log(m.has(o));// 存储值的数量console.log(m.size);

 

Map集合的遍历方法:

1.  forEach

2. for of

        // Map 映射let m = new Map();m.set("a", 1);m.set(true, false);var o = { a: 1 };var o1 = { a: 2 };m.set(o, o1);// 遍历mapm.forEach((value, key) => {console.log(value, key);})

        // Map 映射let m = new Map();m.set("a", 1);m.set(true, false);var o = { a: 1 };var o1 = { a: 2 };m.set(o, o1);// 解构for (let [key, value] of m) {console.log(key, value);}

        // Map 映射let m = new Map();m.set("a", 1);m.set(true, false);var o = { a: 1 };var o1 = { a: 2 };m.set(o, o1);// 只遍历keyfor (var key of m.keys()) {console.log(key);}// 只遍历valuefor (var value of m.values()) {console.log(value);}

        let m = new Map();m.set("a", 1);m.set(true, false);var o = { a: 1 };var o1 = { a: 2 };m.set(o, o1);// m.entries() 获取map的迭代器for (let [key, value] of m.entries()) {console.log(key, value);}

 

注意!!! 

Map参数只能放入迭代器。

可以使用以下的方法传参:

  1. Object.entries(对象) :将对象转换为二维数组的迭代器。
  2. 使用直接迭代器传参。
  3. 使用解构赋值传参。

Object.fromEntries(迭代器) :将迭代器转换为对象

        var obj = { a: 1, b: 2, c: 3 };// Object.entries() 将转换为二维数组的迭代器console.log(Object.entries(obj));var m = new Map(Object.entries(obj));console.log(m);

7.2 Map映射的应用场景

用在循环链表

需求:点击按钮1,按钮2激活;点击按钮2,按钮3激活;...点击按钮6,按钮1激活。

<body><button>按钮1</button><button>按钮2</button><button>按钮3</button><button>按钮4</button><button>按钮5</button><button>按钮6</button><script>//点击按钮1,按钮2激活;点击按钮2,按钮3激活;...点击按钮6,按钮1激活var bns = document.querySelectorAll("button");var m = new Map();bns.forEach((item, index) => {//index的索引不是按钮1的索引下标,则不按钮隐藏if (index != 0) item.disabled = true;//是的按钮1的索引下标,则添加一个侦听事件, { once: true }执行一次该事件后就删除该事件else item.addEventListener("click", clickHandler, { once: true });//按钮1是key,按钮2是按钮1的value值,以此类推...//??是判断一个东西是否存在,按钮6存储的是按钮1m.set(item, bns[index + 1] ?? bns[0]);});function clickHandler(e) {//点击按钮1时,按钮1隐藏。this.disabled = true;//获取当前对象对应的value值,这里就是按钮2。显示按钮2m.get(this).disabled = false;m.get(this).addEventListener("click", clickHandler, { once: true });}</script>
</body>

8. WeakMap映射

        WeakMap 对象是一组键/值对的集合,其中的键是弱引用的。其键必须是引用类型,而值可以是任意的参数是一个数组或者其他可迭代的且元素是键值对的对象。每个键值对会被加到新的 WeakMap 里。null 会被当做 undefiend。所以 WeakMap 不像 Map,一是没有遍历操作(即没有 keys()、values() 和 entries() 方法),也没有 size 属性,也不支持 clear 方法,所以 WeakMap 只有四个方法可用:get()、set()、has()、delete()。

        // WeakMap 的key只能引用类型,不能遍历let o = { a: 1 };let m = new WeakMap();m.set(o, 1);o = null;console.log(m);console.dir(Object);console.log({});

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • EasyCVR中的H.265技术:助力实现大规模高效流畅的视频监控应用
  • Spring中基于redis stream 的消息队列实现方法
  • 计算机网络(一) —— 网络基础入门
  • codetest
  • (二)Kafka离线安装 - Zookeeper下载及安装
  • Golang | Leetcode Golang题解之第383题赎金信
  • 达梦数据库-DM8 企业版安装指南
  • 使用IoC容器--Ninject
  • 【Unity】子物体旋转变形的解决方法
  • Windows上MSYS2的安装和使用
  • 认知杂谈30
  • uni-app 获取当前位置的经纬度以及地址信息
  • 投保单号和保单号码
  • GeoScene Pro教程(005):GeoScenePro移动地理数据库
  • Open3D mesh 模型精细化处理--中点剖分
  • @angular/forms 源码解析之双向绑定
  • java 多线程基础, 我觉得还是有必要看看的
  • java8 Stream Pipelines 浅析
  • Javascript Math对象和Date对象常用方法详解
  • JavaScript设计模式系列一:工厂模式
  • js ES6 求数组的交集,并集,还有差集
  • JS函数式编程 数组部分风格 ES6版
  • js如何打印object对象
  • linux安装openssl、swoole等扩展的具体步骤
  • MySQL常见的两种存储引擎:MyISAM与InnoDB的爱恨情仇
  • react 代码优化(一) ——事件处理
  • vue.js框架原理浅析
  • vue数据传递--我有特殊的实现技巧
  • windows下使用nginx调试简介
  • 爱情 北京女病人
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 机器学习学习笔记一
  • 实现简单的正则表达式引擎
  • Nginx实现动静分离
  • 组复制官方翻译九、Group Replication Technical Details
  • ​LeetCode解法汇总1276. 不浪费原料的汉堡制作方案
  • #{}和${}的区别是什么 -- java面试
  • #WEB前端(HTML属性)
  • (4)logging(日志模块)
  • (Arcgis)Python编程批量将HDF5文件转换为TIFF格式并应用地理转换和投影信息
  • (PySpark)RDD实验实战——取最大数出现的次数
  • (zz)子曾经曰过:先有司,赦小过,举贤才
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (三)Honghu Cloud云架构一定时调度平台
  • (四) 虚拟摄像头vivi体验
  • (四)opengl函数加载和错误处理
  • (一)SvelteKit教程:hello world
  • (一)WLAN定义和基本架构转
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (转)菜鸟学数据库(三)——存储过程
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • ***详解账号泄露:全球约1亿用户已泄露
  • .Net Core中Quartz的使用方法
  • .Net Framework 4.x 程序到底运行在哪个 CLR 版本之上
  • .NET MAUI Sqlite程序应用-数据库配置(一)