eslint推荐编码规范和airbnb推荐编码规范
Eslint规范
-
for 循环禁止使用无限循环(这个非默认推荐)
// bad for (var i = 0; i < 10; i--) { } for (var i = 10; i >= 0; i++) { } // good for (var i = 0; i < 10; i++) { }
-
不允许和负0比较
// bad if (x === -0) { // doSomething()... } // good if (x === 0) { // doSomething()... } if (Object.is(x, -0)) { // doSomething()... }
-
禁止在条件语句(if,while,do...while )中出现赋值操作
// bad if (user.jobTitle = "manager") { // user.jobTitle is now incorrect } // good if (user.jobTitle == "manager") { // doSomething()... }
注意:该规则有个字符串选项,默认是“except-parens”,允许出现赋值操作,但必须是被圆括号括起来的;设置为“always”表示禁止在条件语句中出现赋值语句
// bad 设置为except-parens var x; if (x = 0) { var b = 1; } function setHeight(someNode) { "use strict"; do { someNode.height = "100px"; } while (someNode = someNode.parentNode); } // good 设置为except-parens var x; if (x === 0) { var b = 1; } function setHeight(someNode) { "use strict"; do { someNode.height = "100px"; } while ((someNode = someNode.parentNode)); }
-
禁止在代码中使用console(在产品发布之前,剔除console的调用)
// bad console.log("Log a debug level message."); console.warn("Log a warn level message."); console.error("Log an error level message.") // good //自定义的Console Console.log("Log a debug level message.");
注意:可以设置allow参数允许console 对象方法
-
禁止在条件语句(for,if,while,do...while)和三元表达式(?:)中使用常量表达式
// bad if (false) { doSomething(); } if (2) { doSomething(); } for (;-2;) { doSomething(); } while (typeof x) { doSomething(); } do{ doSomething(); } while (x = -1); var result = 0 ? a : b; // good if (x === 0) { doSomething(); } for (;;) { doSomething(); } while (typeof x === "undefined") { doSomething(); } do{ doSomething(); } while (x); var result = x !== 0 ? a : b;
注意:可以通过设置checkLoops参数来表示是否允许使用常量表达式
-
禁用debugger,采用断点的方式进行调试
// bad function isTruthy(x) { debugger; return Boolean(x); } // good function isTruthy(x) { return Boolean(x); // set a breakpoint at this line }
-
不允许在函数(function)定义里面出现重复的参数(箭头函数和类方法设置重复参数会报错,但跟该规则无关)
// bad function foo(a, b, a) { console.log("value of the second a:", a); } var bar = function (a, b, a) { console.log("value of the second a:", a); }; // good function foo(a, b, c) { console.log(a, b, c); } var bar = function (a, b, c) { console.log(a, b, c); }; // 箭头函数报错 function foo(x, x, y = 1) { //doSomething(); } // SyntaxError: Duplicate parameter name not allowed in this context
-
不允许对象字面量出现重复的key
// bad var foo = { bar: "baz", bar: "qux" }; var foo = { "bar": "baz", bar: "qux" }; var foo = { 0x1: "baz", 1: "qux" }; // good var foo = { bar: "baz", foo: "foo" };
-
不允许使用重复的case值
// bad var a = 1; var b = 1; switch (a) { case 1: break; case 2: break; case 1: // duplicate test expression break; default: break; } switch (a) { case b: break; case 2: break; case b: // duplicate test expression break; default: break; } switch (a) { case ‘1‘: break; case 2: break; case ‘1‘: // duplicate test expression break; default: break; } //good var a = 1; switch (a) { case 1: break; case 2: break; case 3: // duplicate test expression break; default: break; }
-
不允许出现空块语句
// bad if (foo) { } try { doSomething(); } catch(ex) { } finally { } //good if (foo) { // empty } try { doSomething(); } catch (ex) { // continue regardless of error }
注意:可以通过allowEmptyCatch为true允许出现空的catch子句
-
不允许在正则表达式中出现空字符集
// bad /^abc[]/.test("abcdefg"); // false "abcdefg".match(/^abc[]/); // null // good /^abc/.test("abcdefg"); // true "abcdefg".match(/^abc/); // ["abc"] /^abc[a-z]/.test("abcdefg"); // true "abcdefg".match(/^abc[a-z]/); // ["abcd"]
-
不允许对catch子句的参数进行重新赋值
// bad try { // code } catch (e) { e = 10; } // good try { // code } catch (e) { var foo = 10; }
-
禁止不必要的布尔类型转换
// bad var bar = ‘zhinanzhen‘; var foo = !!!bar;//与!bar值相同,都为false var foo = !!bar ? baz : bat; var foo = Boolean(!!bar); if (Boolean(foo)) { // ... } // good var foo = !!bar;//转布尔值 var foo = Boolean(bar); function foo() { return !!bar; } var foo = bar ? !!baz : !!bat;
-
禁止不必要的分号和括号
// bad var x = 5;; function foo() { // code }; a = (b * c); // good var x = 5; var foo = function() { // code } a = b * c;
-
不允许对function重新赋值
// bad var bar = 5;; function foo() {} foo = bar; function foo() { foo = bar; } // good var foo = function () {} foo = bar; function foo(foo) { // `foo` is shadowed. foo = bar; } function foo() { var foo = bar; // `foo` is shadowed. }
-
不允许在嵌套的语句块中用var声明变量和function
// bad if (test) { function doSomethingElse () { //code } } // good function doSomething() { const a = 1; }
注意:
- "functions" (默认) 禁止 function 声明出现在嵌套的语句块中
- "both" 禁止 function 和 var 声明出现在嵌套的语句块中
-
不允许在正则表达式中使用控制字符,即不可显示的字符(在ASCII码中,第0~31号及第127号是控制字符或通讯专用字符)
// bad var pattern1 = /\x1f/; var pattern2 = new RegExp("\x1f");
// good var pattern1 = /\x20/; var pattern2 = new RegExp("\x20");
```
-
不允许RegExp构造函数中出现无效的正则表达式
// bad RegExp(‘[‘);//无效,报错,RegExp(‘[]‘)有效 // good RegExp(‘.‘);//‘.‘元字符查找单个字符
-
不允许正则表达式字面量中出现多个空格
// bad var re = /foo bar/; // good var re = /foo {3}bar/;
-
定义函数时,空格的使用(参考airbnb规范的30-34条)
// bad function thing() /*<NBSP>*/{//使用了多个空格 return ‘test‘; } function thing( /*<NBSP>*/){ return ‘test‘; } // good function thing() { return ‘test‘; } function thing(/*<NBSP>*/) { return ‘test‘; }
注意:
- "skipStrings": true (默认) 允许在字符串字面量中出现任何空白字符
- "skipComments": true 允许在注释中出现任何空白字符
- "skipRegExps": true 允许在正则表达式中出现任何空白字符
- "skipTemplates": true 允许在模板字面量中出现任何空白字符
-
不允许将全局对象(这里主要指非函数型和非构造器对象的全局对象,例如:NaN,Infinity,undefined,Math,JSON,Reflect)作为函数进行调用
// bad var math = Math(); var json = JSON(); var reflect = Reflect(); // good function area(r) { return Math.PI * r * r; } var object = JSON.parse("{}"); var value = Reflect.get({ x: 1, y: 2 }, "x");
-
不允许使用稀疏数组
// bad var items = [,]; var colors = [ "red",, "blue" ]; // good var items = []; var items = new Array(23); var colors = [ "red", "blue", ];
-
不允许使用多行表达式(使用分号结尾,避免无关的两条语句被解析成一条语句)
// bad var hello = ‘world‘ [1, 2, 3].forEach(addNumber); // good ar hello = ‘world‘; [1, 2, 3].forEach(addNumber);
-
不允许在return,throw,continue,break后出现执行不到的代码
// bad function foo() { return true; console.log("done"); } // good function bar() { let x = 1; return x; }
-
不允许直接在finally语句中出现控制流语句(return,throw,break,continue)
// bad let foo = function() { try { return 1; } catch(err) { return 2; } finally { return 3; } }; // good let foo = function() { try { return 1; } catch(err) { return 2; } finally { console.log("hola!"); } }; //间接使用 let foo = function() { try { return 1; } catch(err) { return 2; } finally { let a = function() { return "hola!"; } } };
-
否定操作的使用
// bad if (!key in object) { // doSomthing() } // good if (!(key in object)) { // doSomthing() }
-
检查非数值(NaN)必须使用isNaN()
// bad if (foo == NaN) { // doSomthing() } // good if (isNaN(foo)) { // doSomthing() }
-
typeof 表达式必须与有效的字符串进行比较
// bad typeof foo === "strnig" typeof foo == "undefimed" // good typeof foo === "string" typeof bar == "undefined"
-
不允许在case和default语句中出现词法声明(let,const,function,class),如果需要使用,必须使用花括号
// bad switch (foo) { case 1: let x = 1; break; case 2: const y = 2; break; case 3: function f() {} break; default: class C {} } // good switch (foo) { // The following case clauses are wrapped into blocks using brackets case 1: { let x = 1; break; } case 2: { const y = 2; break; } case 3: { function f() {} break; } case 4: // Declarations using var without brackets are valid due to function-scope hoisting var z = 4; break; default: { class C {} } }
-
不允许case语句落空,可以用throw、return、break或者注释作为结束
// bad switch(foo) { case 1: doSomething(); case 2: doSomethingElse(); } // good switch(foo) { case 1: doSomething(); break; case 2: doSomething(); } switch(foo) { //如果有意落空case语句,需设置commentPattern参数,并且加上注释 case 1: doSomething(); // break omitted case 2: doSomethingElse(); }
-
不允许使用空的解构模式
// bad var {} = foo; var [] = foo; var {a: {}} = foo; var {a: []} = foo; function foo({}) {} function foo([]) {} function foo({a: {}}) {} function foo({a: []}) {} // good var {a = {}} = foo; var {a = []} = foo; function foo({a = {}}) {} function foo({a = []}) {}
-
不允许修改只读的全局变量
// bad Object = null; undefined = 1; window = {};
-
不允许使用8进制字面量(即用0开头的数字)
// bad var num = 071; var result = 5 + 07; // good var num = "071";
-
不允许多次声明同一个变量
// bad var a = 3; var a = 10; // good var a = 3; a = 10;
注意: “builtinGlobals”如果设置为 true,该规则也会检查全局内置对象,比如Object、Array、Number…
-
不允许自己给自己赋值
// bad foo = foo; [a, b] = [a, b]; [a, ...b] = [x, ...b]; ({a, b} = {a, x}); // good foo = bar; [a, b] = [b, a]; let foo = foo;
-
不允许使用没有使用过的标签
// bad A: for (let i = 0; i < 10; ++i) { foo(); } // good B: for (let i = 0; i < 10; ++i) { if (foo()) { break B; } bar(); }
-
不允许使用没有必要的转义
// bad "\‘"; ‘\"‘; "\#"; "\e"; `\"`; `\"${foo}\"`; `\#{foo}`; /\!/; /\@/; // good "\""; ‘\‘‘; "\x12"; "\u00a9"; "\371"; "xs\u2111"; `\``; `\${${foo}\}`; `$\{${foo}\}`; /\\/g; /\t/g; /\w\$\*\^\./;
-
不允许删除变量(严格模式下会报错)
// bad var x; delete x;
-
不允许使用未声明的变量
// bad b = 10; //good let b = 10;
-
定义过的变量都必须被使用
//good let b = 10; alert(b);
-
不允许使用空格和tab混合缩进(airbnb推荐使用两个空格作为缩进)
-
派生类中的构造函数必须调用 super()。非派生类的构造函数不能调用 super()
//bad class A { constructor() { super(); // This is a SyntaxError. } } class A extends B { constructor() { } // Would throw a ReferenceError. } //good class A { constructor() { } } class A extends B { constructor() { super(); } }
-
在派生类构造函数中,不允许在调用super()之前使用this和super
// bad class A extends B { constructor() { this.a = 0; super(); } } class A extends B { constructor() { super.foo(); super(); } } //good class A { constructor() { this.a = 0; // OK, this class doesn‘t have an `extends` clause. } } class A extends B { constructor() { super(); this.a = 0; // OK, this is after `super()`. } }
-
不允许修改类声明的变量
// bad class A { } A = 0; class A { b() { A = 0; } } //good let A = class A { } A = 0; // A is a variable. let A = class { b() { A = 0; // A is a variable. } }
-
禁止修改const声明的变量
// bad const a = 0; a = 1; //good const a = 0; alert(a);
-
Symbol函数前不能使用new命令
// bad var foo = new Symbol("foo"); //good var foo = Symbol("foo"); function bar(Symbol) { const baz = new Symbol("baz"); }
-
不允许使用没有yield的generator 函数
// bad function* foo() { return 10; } //good function* foo() { yield 5; return 10; }
Airbnb规范
-
使用const声明只读的常量,使用let声明可变的变量
// bad var a = 1; var b = 4; if(b > a){ a += 1; } //good let a = 1; const b = 2; if(b > a){ a += 1; }
-
使用字面量创建对象和数组
// bad const item = new Object(); const items = new Array(); //good const item = {}; const items = [];
-
不允许使用关键字作为变量和键值
// bad const default = 0; const superman = { default: { clark: ‘kent‘ }, private: true }; //good const defaults = 0; const superman = { defaults: { clark: ‘kent‘ }, hidden: true, };
-
向数组添加元素时,使用push函数,不允许使用直接赋值的方式
// bad let items = []; items[items.length] = ‘zhinanzhen‘; //good let items = []; items.push(‘zhinanzhen‘);
-
使用解构赋值的方式复制数组
// bad const len = items.length; const itemsCopy = []; let i; for (i = 0; i < len; i++) { itemsCopy[i] = items[i]; } //good const itemsCopy = [...items];
-
对象转数组使用数组的from方法
const foo = document.querySelectorAll(‘.foo‘); const nodes = Array.from(foo);
-
推荐使用解构存取和多属性对象
// bad function getFullName(user) { const firstName = user.firstName; const lastName = user.lastName; return `${firstName} ${lastName}`; } //good function getFullName(obj) { const { firstName, lastName } = obj; return `${firstName} ${lastName}`; } //best function getFullName({ firstName, lastName }) { return `${firstName} ${lastName}`; }
-
数组推荐使用解构赋值
const arr = [1, 2, 3, 4]; const [first, second] = arr;
-
字符串使用单引号(eslint推荐使用一致的单引号或者双引号)
// bad const name = "zhinanzhen"; // good const name = ‘zhinanzhen‘;
-
***推荐使用模版字符串
function sayHi(name) { return `How are you, ${name}?`; }
-
推荐使用函数声明代替函数表达式(var声明的函数表达式,函数的声明会被提升,但是函数体不会;函数声明的名称和函数体都会被提升)
// bad const foo = function () { //doSomething(); }; // good function foo() { const foo = function () { //doSomething(); }; }
-
不允许在if,while中声明一个函数
// bad let a = 2; if (a > 0){ function foo(){ //doSomething() } }
-
不允许把参数声明为arguments(eslint: 不允许函数的参数重名),且使用rest语法代替arguments
// bad function nope(name, options, arguments) { // ...stuff... } // bad function concatenateAll() { const args = Array.prototype.slice.call(arguments); return args.join(‘‘); } // good function concatenateAll(...args) { return args.join(‘‘); }
-
不允许直接给函数的参数赋值
// bad var b = 1; function count(a = b++) { console.log(a); } count(); // 1 count(); // 2 count(3); // 3 count(); // 3
-
在必须使用函数表达式或者传递一个匿名函数时,使用箭头函数
// bad [1, 2, 3].map(function (x) { return x * x; }); // good [1, 2, 3].map((x) => { return x * x; });
-
推荐使用class,避免直接操作prototype
// bad function Queue(contents = []) { this._queue = [...contents]; } Queue.prototype.pop = function() { const value = this._queue[0]; this._queue.splice(0, 1); return value; } // good class Queue { constructor(contents = []) { this._queue = [...contents]; } pop() { const value = this._queue[0]; this._queue.splice(0, 1); return value; } }
-
使用extend继承
// bad const inherits = require(‘inherits‘); function PeekableQueue(contents) { Queue.apply(this, contents); } inherits(PeekableQueue, Queue); PeekableQueue.prototype.peek = function() { return this._queue[0]; } // good class PeekableQueue extends Queue { peek() { return this._queue[0]; } }
-
不要使用通配符import
// bad import * as AirbnbStyleGuide from ‘./AirbnbStyleGuide‘; // good import AirbnbStyleGuide from ‘./AirbnbStyleGuide‘;
-
不要在import中直接export
// bad // filename es6.js export { es6 as default } from ‘./airbnbStyleGuide‘; // good // filename es6.js import { es6 } from ‘./AirbnbStyleGuide‘; export default es6;
-
使用高阶函数(map(),reduce())替代for-of
const numbers = [1, 2, 3, 4, 5]; // bad let sum = 0; for (let num of numbers) { sum += num; } sum === 15; // good let sum = 0; numbers.forEach((num) => sum += num); sum === 15; // best (use the functional force) const sum = numbers.reduce((total, num) => total + num, 0); sum === 15;
-
访问对象属性使用‘.’,通过变量访问属性时使用中括号‘[]’
const luke = { jedi: true, age: 28, }; // bad const isJedi = luke[‘jedi‘]; // good const isJedi = luke.jedi; function getProp(prop) { return luke[prop]; } const isJedi = getProp(‘jedi‘);
-
将const和let分组
// bad let i, len, dragonball, items = getItems(), goSportsTeam = true; // bad let i; const items = getItems(); let dragonball; const goSportsTeam = true; let len; // good const goSportsTeam = true; const items = getItems(); let dragonball; let i; let length;
-
优先使用 === 和 !== 而不是 == 和 !=.
-
条件表达式里面的值使用简写的方式
// bad if (name !== ‘‘) { // ...stuff... } // good if (name) { // ...stuff... } // bad if (collection.length > 0) { // ...stuff... } // good if (collection.length) { // ...stuff... }
注意:条件表达式例如 if 语句通过抽象方法 ToBoolean 强制计算它们的表达式并且总是遵守下面的规则:
- 对象:true
- Undefined:false
- Null :false
- 布尔值 :布尔的值
- 数字 :+0、-0、或 NaN 算为 false, 否则为 true
- 字符串:如果是空字符串 ‘‘ 为 false,否则为 true
- 数组:true(包括空数组 [] )
-
多行代码使用大括号包裹
// bad if (test) return false; function() { return false; } // good if (test) return false; if (test) { return false; } function() { return false; }
-
如果通过 if 和 else 使用多行代码块,把 else 放在 if 代码块关闭括号的同一行。
// bad if (test) { thing1(); thing2(); } else { thing3(); } // good if (test) { thing1(); thing2(); } else { thing3(); }
-
*** 使用 /** ... */ 作为多行注释,包含描述、指定所有参数和返回值的类型和值。
// bad // make() returns a new element // based on the passed in tag name // // @param {String} tag // @return {Element} element function make(tag) { // ...stuff... return element; } // good /** * make() returns a new element * based on the passed in tag name * * @param {String} tag * @return {Element} element */ function make(tag) { // ...stuff... return element; }
-
使用 // 作为单行注释。在评论对象上面另起一行使用单行注释。在注释前插入空行。
// bad const active = true; // is current tab // good // is current tab const active = true; // bad function getType() { console.log(‘fetching type...‘); // set the default type to ‘no type‘ const type = this._type || ‘no type‘; return type; } // good function getType() { console.log(‘fetching type...‘); // set the default type to ‘no type‘ const type = this._type || ‘no type‘; return type; }
-
给注释增加 FIXME 或 TODO 的前缀可以帮助其他开发者快速了解这是一个需要复查的问题,或是给需要实现的功能提供一个解决方式
// good class Calculator { constructor() { // FIXME: shouldn‘t use a global here total = 0; } } class Calculator { constructor() { // TODO: total should be configurable by an options param this.total = 0; } }
-
使用两个空格作为缩进;
-
大括号前面使用一个空格;
-
在控制语句(if、while 等)的小括号前放一个空格;在函数调用及声明中,不在函数的参数列表前加空格
// bad if(isJedi) { fight (); } // good if (isJedi) { fight(); } // bad function fight () { console.log (‘Swooosh!‘); } // good function fight() { console.log(‘Swooosh!‘); }
-
使用空格把运算符隔开;
// bad const x=y+5; // good const x = y + 5;
-
在文件末尾,块儿末,新语句前插入空行插入一个空行
// bad if (foo) { return bar; } return baz; // good if (foo) { return bar; } return baz; // bad const obj = { foo() { }, bar() { }, }; return obj; // good const obj = { foo() { }, bar() { }, }; return obj;
-
不要在行首插入逗号
// bad const story = [ once , upon , aTime ]; // good const story = [ once, upon, aTime, ];
-
给对象定义属性的时候增加结尾的逗号
// bad const story = [ firstName: ‘Dana‘, lastName: ‘Scully‘, ]; // good const story = [ firstName: ‘Dana‘, lastName: ‘Scully‘, ];
-
分号的使用
// bad (function() { const name = ‘Skywalker‘ return name })() // good (() => { const name = ‘Skywalker‘; return name; })(); // good (防止函数在两个 IIFE 合并时被当成一个参数) ;(() => { const name = ‘Skywalker‘; return name; })();
-
在语句开始前执行类型转换
// => this.reviewScore = 9; // bad const totalScore = this.reviewScore + ‘‘; // good const totalScore = String(this.reviewScore);
-
对数字使用 parseInt 转换,并带上类型转换的基数
const inputValue = ‘4‘; // bad const val = new Number(inputValue); // bad const val = +inputValue; // bad const val = inputValue >> 0; // bad const val = parseInt(inputValue); // good const val = Number(inputValue); // good const val = parseInt(inputValue, 10);
-
在使用长方法链时进行缩进。使用前面的点 . 强调这是方法调用而不是新语句
// bad $(‘#items‘).find(‘.selected‘).highlight().end().find(‘.open‘).updateCount(); // bad $(‘#items‘). find(‘.selected‘). highlight(). end(). find(‘.open‘). updateCount(); // good $(‘#items‘) .find(‘.selected‘) .highlight() .end() .find(‘.open‘) .updateCount();
-
使用具有意义的命名方式
// bad function q() { // ...stuff... } // good function query() { // ..stuff.. }
-
使用驼峰命名对象和函数
// bad const OBJEcttsssss = {}; const this_is_my_object = {}; function c() {} // good const thisIsMyObject = {}; function thisIsMyFunction() {}
-
使用帕斯卡式(首字母大写)命名构造函数或类
// bad function user(options) { this.name = options.name; } const bad = new user({ name: ‘nope‘, }); // good class User { constructor(options) { this.name = options.name; } } const good = new User({ name: ‘yup‘, });
-
不要使用下划线 _ 结尾或开头来命名属性和方法
// bad this.__firstName__ = ‘Panda‘; this.firstName_ = ‘Panda‘; this._firstName = ‘Panda‘; // good this.firstName = ‘Panda‘;
-
不要保存this的引用,使用箭头函数或者bind保存
// bad function foo() { const self = this; return function() { console.log(self); }; } // bad function foo() { const that = this; return function() { console.log(that); }; } // good function foo() { return () => { console.log(this); }; }
-
如果文件只有一个类,那文件名必须与类名保持一致
// file contents class CheckBox { // ... } export default CheckBox; // in some other file // bad import CheckBox from ‘./checkBox‘; // bad import CheckBox from ‘./check_box‘; // good import CheckBox from ‘./CheckBox‘;
-
存取函数时使用getVal() 和 setVal(‘hello‘)
// bad echeng.age(); // good echeng.getAge(); // bad echeng.age(25); // good echeng.setAge(25);
-
属性是布尔值的时候使用isVal() 或 hasVal()
// bad if (!dragon.age()) { return false; } // good if (!dragon.hasAge()) { return false; }
-
set()和get()要保持一致
set(key, val) { this[key] = val; } get(key) { return this[key]; }
-
缓存jQuery查询
// bad function setSidebar() { $(‘.sidebar‘).hide(); // ...stuff... $(‘.sidebar‘).css({ ‘background-color‘: ‘pink‘ }); } // good function setSidebar() { const $sidebar = $(‘.sidebar‘); $sidebar.hide(); // ...stuff... $sidebar.css({ ‘background-color‘: ‘pink‘ }); }
-
使用 $ 作为存储 jQuery 对象的变量名前缀
// bad const sidebar = $(‘.sidebar‘); // good const $sidebar = $(‘.sidebar‘);
-
对DOM查询使用层叠 $(‘.sidebar ul‘) 或 父元素 > 子元素 $(‘.sidebar > ul‘)的方式
-
对有作用域的jQuery对象查询使用 find
// bad $(‘ul‘, ‘.sidebar‘).hide(); // bad $(‘.sidebar‘).find(‘ul‘).hide(); // good $(‘.sidebar ul‘).hide(); // good $(‘.sidebar > ul‘).hide(); // good $sidebar.find(‘ul‘).hide();
-