面向对象编程02,作用域与作用域链

JS中效能域的定义:
表示变量或函数起效果的区域,指代了它们在如何的光景文中实施,亦即上下文执市场价格况。Javascript的效能域唯有三种:全局功用域和地面效率域,本地作用域是服从函数来差异的。
首先来看几道难题: 1. 复制代码 代码如下:
if{ var aa= “bb”; } console.log; //bb for(var i = 0; i < 100; i++卡塔尔(英语:State of Qatar){
//do } console.log; //100 2. 复制代码
代码如下: var bb = ‘11111’; function aa;//undefine var bb = ‘test’;
alert;//test var cc = “test1”; alert; 3. 复制代码 代码如下: var test = ‘1111111’;
function aa; } function bb(卡塔尔(英语:State of Qatar) { var test = ‘22222222’; aa;//alert; 4.
复制代码 代码如下: alert; //function
alert; //undefined function aa(卡塔尔(英语:State of Qatar) { //函数定义式 alert; }; var bb =
function(卡塔尔国 { //函数表明式 } alert;//function 5. 复制代码 代码如下: function aa(卡塔尔(英语:State of Qatar){ var bb =
“test”; cc = “测验”; alert; alert;//语法报错
上边这5道标题全部包罗了js中成效域的难点 能够计算出这么多少个意见
黄金年代、无块级效能域
从第意气风发题中能够看出来,在{}中推行后,变量并从未被消逝,如故保存在内部存款和储蓄器中的,因而大家得以访问到的。
二、JavaScript中的函数运转在它们被定义的功用域里,并非它们被试行的功用域里.
这里提到函数的效果与利益域链那些定义,在ECMA26第22中学,是这么的
任何推行上下文时刻的作用域, 都是由效能域链来落到实处.
在一个函数被定义的时候, 会将它定义时候的scope
chain链接到那些函数对象的[[scope]]属性.
在八个函数对象被调用的时候,会成立叁个运动目的,
然后对于每三个函数的形参,都命名字为该活动目的的命名属性,
然后将那几个运动对象做为那时候的成效域链最前端,
并将以此函数对象的[[scope]]参与到scope chain中. 所以标题3
结果是alert; 三、JS会提前管理function定义式 和var关键字 如标题4
开头alert; //undefine
,alert//语法报错,那多个有哪些分化吗,原因就是前面有var bb
=“test”,在带头化的时候提前管理了var 那个入眼字,只是那一个伊始未赋值
将代码修正成那样的,能够看出来 复制代码
代码如下: var dd = ‘11111’; function aa;//undefine var bb = ‘test’;
alert;//test var cc = “test1”; alert; alert;//语法报错
此处alert报语法错误。 不过请留意: 复制代码 代码如下:

词法作用域

静态效用域又称作词法效用域,接纳词法效能域的变量叫词法变量。词法变量有多个在编写翻译时静态明确的成效域。词法变量的功效域能够是叁个函数或生龙活虎段代码,该变量在这里段代码区域内可知(visibility);在这里段区域以外该变量不可以预知(或无法访问)。词法成效域里,取变量的值时,会检讨函数定义时的文书情形,捕捉函数定义时对该变量的绑定。

在乎一点就是:词法成效域是不可逆的

<pre>

// name = undefined
var scope1 = function () {
// name = undefined
var scope2 = function () {
// name = undefined
var scope3 = function () {
var name = ‘Todd’; // locally scoped
};
};
}
</pre>

3. 成效域链成立法则:

当定义四个函数时(注意,是概念的时候就从头了),它实际上保存三个效果域链。

当调用那几个函数时,它创设一个新的靶子来存款和储蓄它的参数或部分变量,并将以此指标加多保存至那些作用域链上,同一时间创立多个新的更加长的表示函数调用功用域的“链”。

对此嵌套函数来讲,境况又不无扭转:每便调用外界函数的时候,内部函数又会再一次定义二回。因为每一遍调用外界函数的时候,成效域链都以不一致的。内部函数在每趟定义的时候都要微妙的间距—在历次调用外界函数时,内部函数的代码都以同等的,何况涉及这段代码的功力域链也不均等。

(tip:
把地点三点清楚好,记住了,最佳还要能用自身的话讲出来,不然就背下来,因为面试官就间接问您:请描述一下功用域链…卡塔尔国

举个成效域链的实用例子:
var name=”one”;
function test(){
var name=”two”;
function test1(){
var name=”three”;
console.log(name);//three
}
function test2(){
console.log(name);// two
}
test1();
test2();
}
test();
上面是个嵌套函数,相应的相应是意义域链上有五个指标
那就是说在调用的时候,要求搜索name的值,就在功效域链上搜索

当成功调用test1(卡塔尔的时候,顺序为 test1(卡塔尔(قطر‎->test(卡塔尔->全局对象window
因为在test1(卡塔尔上就找到了name的值three,所以形成找寻重临
当成功调用test1(卡塔尔国的时候,顺序为 test2(卡塔尔国->test(卡塔尔->全局对象window
因为在test2(卡塔尔(英语:State of Qatar)上没找到name的值,所以找test(卡塔尔中的,找到了name的值two,就完事找出重返

再有二个例子一时候我们会犯错的,面试的时候也平时上当到。
<html xmlns=”;
<head>
<script type=”text/javascript”>
function buttonInit(){
for(var i=1;i<4;i++){
var b=document.getElementById(“button”+i);
b.addEventListener(“click”,function(){
alert(“Button”+i); //都是 Button4
},false);
}
}
window.onload=buttonInit;
</script>
</head>
<body>
<button id=”button1″>Button1</button>
<button id=”button2″>Button2</button>
<button id=”button3″>Button3</button>
</body>
</html>
为什么?
依赖效果与利益域链中变量的检索法则:
b.addEventListener(“click”,function(){
alert(“Button”+i);
},false);
此间有三个函数,它是无名氏函数,既然是函数,那就在效果与利益域链上独具二个对象,那个函数里边使用到了变量i,它自然会在效率域上搜索它。
搜寻顺序是 那几个无名氏函数 –>外界的函数buttonInit(卡塔尔国–>全局对象window

无名氏函数中找不到i,自然跑到了buttonInit(卡塔尔, ok,在for中找到了,

此刻注册事件已经达成了,不要感觉它会二个三个把i放下来,因为函数成效域之内的变量对效率域内是直接可知的,正是说会维持到最终的情况

当佚名函数要使用i的时候,注册事件完了,i已经形成了4,所以都以Button4

那怎么消灭吧?

给它传值进去吧,每便循环时,再使用二个无名氏函数,把for里边的i传进去,无名氏函数的平整如代码

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“;
<html xmlns=”;
<head>
<script type=”text/javascript”>
function buttonInit(){
for(var i=1;i<4;i++){
(function(data_i){
var b=document.getElementById(“button”+data_i);
b.addEventListener(“click”,function(){
alert(“Button”+data_i);
},false);

           })(i);
   }

}
window.onload=buttonInit;
</script>
</head>
<body>
<button id=”button1″>Button1</button>
<button id=”button2″>Button2</button>
<button id=”button3″>Button3</button>
</body>
</html>
像这种类型就能够 Button1..2..3了

那注脚js预编写翻译是以段为单元的。标题4同理 四、函数级效用域
函数里面包车型地铁定义的变量,在函数实施完后就销毁了,不占用内部存储器区域了。
所以标题2末尾的alert;语法报错,标题5末尾到 alert同理

块级功用域

此外大器晚成对花括号中的语句集都归属三个块,在这里中间定义的持有变量在代码块外都以不可知的,大家称为块级效率域。

大多数类C语言都以有块级效率域的,但是在JS个中是还未块级效率域
<pre>

functin test(){
for(var i=0;i<3;i++){
}
韦德1946娱乐手机版,alert(i);
}
test();

推行结果:弹出”3″
</pre>

足见,在块外,块中定义的变量i仍为足以访问的。

****何以在模拟块级效用域呢?****
首先要通晓某个:在二个函数中定义的变量,当以此函数调用完后,变量会被消逝。利用闭包模拟:
<pre>
function test(){
(function (){
for(var i=0;i<4;i++){
}
})();
alert(i);
}
test();

执行结果:会弹出”i”未定义的不当
</pre>

别的说飞鹤(Karicare卡塔尔国(Dumex卡塔尔些:从ES6方始,你可以因此let关键字来定义变量,它修改了var关键字的欠缺,能够令你像Java语言那样定义变量,况且接济块级作用域。

3. 值得注意的是,上边提到的都未曾传参数,假诺test有参数,又怎么样呢?

console.log(name);//one
name=”two”;
console.log(name);//two
}
var name =”one”;
test(name);
console.log(name);// one
事情发生以前说过,基本类型是按值传递的,所以传进test里面包车型客车name实际上只是三个别本,函数再次来到之后这么些别本就被免去了。
相对不要感觉函数里边的name=”two”把全局name修改了,因为它们是多个独立的name
(2)功用域链
地方提到的高端级函数就事关到了效果域链
function test1(){
var name =”one”;
return function(){
console.log(name);
}
}
test1()();

大局成效域

当大家书写JavaScript代码的时候,所处的成效域正是大家所说的 全局效率域 。

<pre>
//Global Scope
var name = “caicai”;
</pre>

在那间,大家利用它去创制能够在其余功用域访问的模块以至接口

2. JS中的评释提前

js中的函数效用域是指在函数内表明的具备变量在函数体内始终是可以见到的。并且,变量在注解从前就足以行使了,这种气象就叫做表明提前(hoisting卡塔尔(قطر‎
tip:评释提前是在js引擎预编写翻译时就打开了,在代码被实行在此以前已经有扬言提前的情状产生了
比如
var name=”one”;
function test(){
console.log(name);//undefined
var name=”two”;
console.log(name);//two
}
test();
上边就直达了上边包车型客车固守
var name=”one”;
function test(){
var name;
console.log(name);//undefined
name=”two”;
console.log(name);//two
}
test();
再尝试把var去掉?那是函数内的name已经变为了全局变量,所以不再是undefined
var name=”one”;
function test(){
console.log(name);//one
name=”two”;
console.log(name);//two
}
test();

动态功能域

接受动态成效域的变量叫做动态变量。只要程序正在实施定义了动态变量的代码段,那么在这里段日子内,该变量一直存在;代码段实行实现,该变量便未有。举三个例子:假诺有个函数f,里面调用了函数g,那么在实施g的时候,f里的有着片段变量都会被g访谈到。而在在静态成效域的情景下,g不可能采访f的变量。有意思味的能够看这里#Lexical_scoping)
<pre>
var foo=1;
function static(){
alert(foo);
}
function(){
var foo=2;
static();
}();

</pre>

进行结果:会弹出1而非2,因为static的scope在成立时,记录的foo是1。
少年老成经js是动态功用域,那么她应该弹出2。

总的说来,JS不扶持动态成效域~

一、作用域

叁个变量的功能域(scope)是程序源代码中定义的这些变量的区域。

参谋小说

1.http://wwsun.github.io/posts/scope-and-context-in-javascript.html

2.http://ryanmorr.com/understanding-scope-and-context-in-javascript/

3.http://www.html-js.com/article/Sexy-Javascript-understand-the-callback-function-with-the-use-of-Javascript-in

2. 职能域链譬如:

在js最顶层代码中(也正是不包含其余函数定义内的代码),成效域链由贰个大局对象组成。
在不分包嵌套的函数体内,作用域链上有五个指标,第几个是概念函数参数和局部变量的对象,第叁个是全局对象。
在二个嵌套的函数体内,功效域上至稀有三个对象。

怎么着是作用域?

以下来自于百度宏观的定义:

日常来讲,意气风发段程序代码中所用到的名字并不三番两次实惠/可用的,而节制那一个名字的可用性的代码范围正是其一名字的成效域。
作用域的行使指标是为着拉长了程序逻辑的区域性,加强程序的可信性,缩小名字冲突。

在JavaScript中,效用域指的是您代码的眼下上下文情形

补充

函数的历次调用都有与之严格有关的作用域和上下文。从根本上来讲,作用域是基于函数的,而上下文是依据对象的。
换句话说,作用域涉及到所被调用函数中的变量访谈,况且不一样的调用项景是不一致等的。上下文始终是this关键字的值,
它是颇有(调控)当前所实施代码的指标的引用。

4.上述便是效果与利益域链的中央描述,其余,with语句可用于有的时候拓宽成效域链(不引进应用with)

语法形如:
with(object)
statement
以此with语句,将object增加到效用域链的底部,然后奉行statement,最终把功用域链苏醒到原始状态
轻易用法:
比如给表单中逐意气风发项的值value赋值
诚如能够我们一向这样
var f = document.forms[0];
f.name.value =””;
f.age.value =””;
f.email.value =””;
引进with后(因为运用with会产生生机勃勃多元难点,所以照旧使用方面那张方式吧)
with
(document.forms[0]){
f.name.value =””;
f.age.value =””;
f.email.value =””;
}

除此以外,借使 三个指标o具有x属性,o.x = 1;
那正是说使用
with(o){
x = 2;
}
就足以调换到 o.x = 2;
借使o未有概念属性x,它的成效就只是也正是 x = 2; 三个全局变量罢了。
因为with提供了生机勃勃种读取o的习性的快捷方式,但她并不能够创设o本人并未有的本性。
要明白变量的成效域范围就得先知道效率域链
用var关键字声美赞臣个变量时,正是为该变量所在的对象加多了一个本性。
意义域链:由于js的变量都以目的的性质,而该对象恐怕又是此外对象的习性,而持有的指标都以window对象的性情,所以那几个目的的关联足以充作是一条链
链头就是变量所处的对象,链尾便是window对象

看上边包车型客车代码:
复制代码 代码如下:

function t() {
var a;
function t2() {
var b;
}
}

js中等高校函授数也是目的,所以变量a所在的靶子是t,t又在window对象中,所以a的功用域链如下
t–window
那就是说b所以在的对象即t2,t2又包罗在t中,t又在window对象,所以b的功能域链如下
t2–t–window
明白了成效域链下边就起来变量的作用域剖判了
1 javascript 未有var的变量都为全局变量,且为window对象的天性
复制代码 代码如下:

function test1() {
//实施那些句的时候它会找功能域对象,那一个函数就是功力域链中的第三个对象,但这一个指标中绝非有关的var语句
//于里就找成效域链的第二个目的,即全局对象,而全局对象中也未曾相关的var语句
//由于未有有关的var语句,js隐式在函数地声称了变量即var all;
all = 30;
alert(all);
}
test1();
alert(all);
alert(window.all);

2 函数内(函数内的函数除此之外卡塔尔国定义的变量在一切函数内部都使得
复制代码 代码如下:

function test2() {
var t = 0;
//在for的法规里定义变量,那些改造的效果与利益域链对象是这几个函数
//因而在全部的函数里它是实用的
for (var i = 0; i < 5; i++) {
t += i;
}
alert(i);
}
test2();

3 函数内部的变量替代全局同名变量
复制代码 代码如下:

var t = “bb”;
function test() {
//推行t的时候,它会先找效能域链对象,由于它定义在函数内部,所以那些函数正是它的功用域链的率先个目的
//而在这里个指标里又有t的定义,所以t正是局地变量了,它替换了大局变量t
//t只是那个时候有定义,但并不曾赋值,赋值在下意气风发行,所以这里出口了undefined
alert(t);
var t = “aa”;
alert(t);
}
test();

4 没块的成效域
复制代码 代码如下:

if (true) {
//在块中定义了二个变量,它的效果与利益域链的率先个对象就是全局对象window
var tmp = 0;
}
//tmp的功能域链的第一个对象正是大局对象window,而地点又有大局对象中相关的var语句,由此输出0
alert(tmp);

以下内容来自读网络博客的总计,当笔记使用,只记注重,同不日常间非常多谢乐于分享的博主们,是你们让自个儿站在了圣人的肩旁上!
1、
复制代码 代码如下:

var temp = (function(){
var name =”test”;
return function(){
alert(name);
}
})();

上述代码片断是我们jser经不足为道到的写法,是遗闻中的闭包。 赫赫有名:调用
temp(卡塔尔(قطر‎;会弹出 “ test”;该进度能够有以下三条理论作为基于来解说:

1)js 功用域只和函数的范围符相关,函数与函数的嵌套产生了意义域链;
2)功效域链的创建法规是复制上生龙活虎层情形的效果与利益域链,并将指向本情状变量对象的指针放到链首;
3)在Javascript中,若是三个对象不再被援用,那么那几个目的就能被GC回笼。要是多个目的相互引用,而不再被第3者所援引,那么那四个相互引用的对象也会被回笼。

闭包用场

  • 模块形式:允许你模仿公共的、私有的、和特权成员

<pre>
var Module = (function(){
var privateProperty = ‘foo’;

function privateMethod(args){
    // do something
}

return {

    publicProperty: '',

    publicMethod: function(args){
        // do something
    },

    privilegedMethod: function(args){
        return privateMethod(args);
    }
};

})();

</pre>

模块相同于叁个单例对象。由于在上头的代码中大家接受了(function(卡塔尔国 { …
}卡塔尔国(卡塔尔(英语:State of Qatar);的佚名函数情势,因而当编写翻译器解析它的时候会及时奉行。
在闭包的实行上下文的外界唯生机勃勃能够访问的靶子是坐落于再次来到对象中的公共艺术和性质。但是,因为实施上下文被封存的来头,
全体的私家眷性和方式将平素存在于采纳的全套生命周期,那代表大家唯有经过集体艺术才方可与它们相互。

  • 旋即推行的函数表明式

<pre>
(function(window){
var foo, bar;
function private(){
// do something
}
window.Module = {
public: function(){
// do something
}
};
})(this);
</pre>
对此维护全局命名空间免受变量污染来讲,这种表明式非常常有用,它经过创设函数功效域的花样将变量与全局命名空间隔离,
并通过闭包的款式让它们存在于一切运营时(runtime)。在超级多的利用和框架中,这种封装源代码的章程用场特别的风靡,
常常都以通过揭示一个单意气风发的大局接口的艺术与外表实行交互作用。

1. 引进一大段话来阐明:

每一段js代码(全局代码或函数)都有一个与之提到的功用域链(scope
chain)。
以此效果域链是三个对象列表只怕链表,这组对象定义了这段代码中“成效域中”的变量。
当js必要探求变量x的值的时候(那些进度称为变量拆解深入分析(variable
resolution)),它会从链的第一个目的伊始查找,假设那几个指标有三个名称为x的质量,则会直接行使那天个性的值,要是第一个指标中平素不名叫x的习性,js会继续查找链上的下贰个对象。假诺第二个目的仍旧没盛名叫x的个性,则会继续查找下二个,就那样推算。假设效果域链上并未有任何二个目的包括属性x,那么就以为这段代码的法力域链上官样文章x,并最后抛出叁个援用错误(ReferenceError)非常。

其他

对此其他改变成效域的主意,后续小说介绍,举例 : call,apply,bind
,ES6的箭头函数等等

1. 在JS中应用的是词法成效域(lexical scope卡塔尔(قطر‎

不在任何函数内注明的变量(函数内省略var的也算全局)称作全局变量(global
scope)
在函数内申明的变量具有函数功能域(function scope),归属有个别变量

豆蔻梢头部分变量优先级高于全局变量
var name=”one”;
function test(){
var name=”two”;
console.log(name);
//two
}
test();
函数内省略var的,会影响全局变量,因为它其实已经被重写成了全局变量
var name=”one”;
function test(){
name=”two”;
}
test();
console.log(name);//two
函数效能域,正是说函数是三个功能域的主导单位,js不像c/c++那样富有块级功效域
比如 if for 等
function test(){
for(var i=0;i<10;i++){
if(i==5){
var name =”one”;
}
}
console.log(name);//one
}
test(卡塔尔(英语:State of Qatar);//因为是函数级功能域,所以能够访谈到name=”one”

当然了,js里边还使用到了高阶函数,其实能够领悟成嵌套函数
functiontest1(){
var name =”one”;
return function(){
console.log(name);
}
}
test1()();
test1(卡塔尔之后将调用外层函数,重临了叁个内层函数,再持续(卡塔尔国,就相应调用推行了内层函数,所以就输出
”one”
嵌套函数涉及到了闭包,前面再谈..这里内层函数能够访谈到外围函数中声称的变量name,这就关系到了功效域链机制

函数成效域

JavaScript中颇有的成效域在创设的时候都只伴随着 函数成效域 ,循环语句像
for 可能 while ,条件语句像 if 或许switch,归于块功用域范畴,由于js荒诞不经块级效率域,所以都不可以知道发出新的效应域.
准则:新的函数 = 新的功用域

<pre>
// Scope A
var myFunction = function () {
// Scope B
var myOtherFunction = function () {
// Scope C
};
};

</pre>

闭包

闭包是指有权访问另大器晚成函数功用域中的变量的函数。换句话说,在函数内定义两个嵌套的函数时,就构成了一个闭包,
它同意嵌套函数访问外层函数的变量。通过再次回到嵌套函数,允许你维护对表面函数中部分变量、参数、和内函数宣称的访谈。
这种封装允许你在外部效能域中潜藏和护卫施行情状,况且暴光公共接口,进而通过公共接口履行更加的操作。

<pre>
var sayHello = function (name) {
var text = ‘Hello, ‘ + name;
return function () {
console.log(text);
};
};

调用格局:
var helloTodd = sayHello(‘Todd’);
helloTodd(); // will call the closure and log ‘Hello, Todd’

or

sayHello(‘Bob’)();

</pre>

作用域分类

功能域链

再此之前,请先领会下js预编写翻译和进行进程

今世码在几个条件中进行时,会创制变量对象的二个功力域链(scope
chain);它为三个加以的函数创立了作用域,保障对推行意况有权访谈的拥有变量和函数的不改变访问。
成效域链包蕴了在条件栈中的种种实施情形对应的变量对象。通过成效域链,能够决定变量的寻访和标记符的解析。
注意,全局试行意况的变量对象始终都以职能域链的最终三个对象。

即使JS的语法风格和C/C++相仿,
但效能域的落到实处却和C/C++差异,并不是用“仓库”方式,而是动用列表,具体经过如下(ECMA26第22中学所述卡塔尔(英语:State of Qatar):

其余实施上下文时刻的功用域, 都以由成效域链(scope chain, 前面介绍卡塔尔(قطر‎来达成.

在叁个函数被定义的时候, 会将它定义时刻的scope
chain链接到这些函数对象的[[scope]]属性.

在叁个函数对象被调用的时候,会创建多个平移指标(也正是三个对象卡塔尔国,
然后对于每二个函数的形参,都命名称为该活动对象的命名属性,
然后将那几个运动指标做为当时的成效域链(scope chain卡塔尔国最前端,
并将这一个函数对象的[[scope]]加入到scope chain中.

下边大家由此代码俩讲师下一下:

<pre>
var rain = 1;
function rainman(){
var man = 2;
function inner(){
var innerVar = 4;
alert(rain);
}
inner(); //调用inner函数
}
rainman(); //调用rainman函数
</pre>

透过js预编写翻译和实行进度来深入分析:
<pre>

Global LE = {
rainman:对函数引用
rain:1

}

rainman LE {
innerVar :对函数援用
man:2;
}

inner LE {
innerVar:4
}

</pre>

观望alert(rain卡塔尔国;那句代码。JavaScript首先在inner函数中找出是还是不是定义了变量rain,假诺定义了则应用inner函数中的rain变量;假使inner函数中从未定义rain变量,JavaScript则会继续在rainman函数中寻找是或不是定义了rain变量,在这里段代码中rainman函数体内未有定义rain变量,则JavaScript引擎会三回九转上扬(全局对象)查找是还是不是定义了rain;在大局对象中我们定义了rain
= 1,因而最后结果会弹出’1’。

效用域链:JavaScript供给查询贰个变量x时,首先会找寻功效域链的第三个对象,假若以第多个目的未有定义x变量,JavaScript会一连搜寻有未有定义x变量,要是第三个目的未有概念则会持续查找,就这样推算。

地点的代码涉及到了八个作用域链对象,依次是:inner、rainman、window。

总的说来,结合js预编写翻译和施行进度来看,函数对象的[[scope]]性子是在概念一个函数的时候决定的,
而非调用的时候
並且内部条件足以经过功用域链访问具备的外界意况,但是外界景况无法访谈内部条件中的任何变量和函数。
那几个景况之间的维系是线性的、鱼贯而入的。

对此标志符剖析(变量名或函数名找出)是沿着功用域链顶级一流地查找标志符的经过。搜索进度始终从作用域链的前端伊始,
然后逐级地向后(全局履行遇到)回溯,直到找到标志符停止。

总结:

1.第生机勃勃掌握 JS 预编写翻译和试行进度,有扶持精晓jS功效域链

2.闭包的引进带给了之类好处:

  • 减少全局变量
  • 压缩了传递给函数的参数变量
  • 封装

发表评论

电子邮件地址不会被公开。 必填项已用*标注