• 使用 4 个空格作为缩进,并且禁止把空格和tab键混用来进行缩进。 eslint: indent eslint: no-mixed-spaces-and-tabs

  • 在大括号前放一个空格。 eslint: space-before-blocks

  • 在JavaScript的关键字( if while 等)后要放一个空格。在函数调用时,不在函数的参数列表前加空格。 eslint: keyword-spacing eslint: func-call-spacing eslint: no-spaced-func

  • 使用空格把运算符隔开。 eslint: space-infix-ops

  • for循环内,分号后面要加上空格。 eslint: semi-spacing

  • 在文件末尾插入一个空行。 eslint: eol-last

  • 在代码块的始末和新语句前插入空行,并且在代码块前添加空格。 eslint: space-before-blocks

    // bad
    function bar(){
        if (foo) {
            return bar;
      return baz;
    // good
    function bar() {
        var obj = {
            foo: function () {
            bar: function () {
        return obj;
    
  • 避免在正则表达式中使用多个空格。

  • 在对象的属性中,要求键名与冒号之间没有空格,冒号与值之间有一个空格。 eslint:key-spacing

  • 在一元字母运算符前后需要加空格,如:new,delete,typeof,void,yield。一元运算符如-,+,--,++,!,!!前后不用加空格。 eslint:space-unary-ops

  • 避免在逻辑表达式、条件表达式、声明语句、数组元素、对象属性、序列、函数参数中使用多个空格,除了连续使用多个空格用于缩进以外,其他情况下连续使用多个空格通常是错误的。 eslint:no-multi-spaces

  • 禁止在数组的左右方括号与数组元素之间有空格。 eslint:array-bracket-spacing

  • 单行代码块中,块中代码行前后需要留空白。 eslint:block-spacing

    // bad
    function foo() {return true;}
    if (foo) { bar = 0;}
    function baz() {var i = 0;
        return i;
    // good
    function foo() { return true; }
    if (foo) { bar = 0; }
    
  • 分号前面不应该有空格,分号后面有空格。 eslint: semi-spacing

  • 规定逗号后面应该留一个空格。 eslint: comma-spacing

  • 禁止通过[]访问对象属性时方括号内有空格。 eslint: computed-property-spacing

  • 代码中最多连续使用两行空行。 eslint: no-multiple-empty-lines

  • 禁止行末尾有空格。 eslint: no-trailing-spaces

  • 如果对象的属性位于同一行,则此规则不允许在点周围或开始括号之前的空格。当对象和属性位于不同的行时,此规则允许使用空格,因为通常将新行添加到较长的属性链。 eslint: no-whitespace-before-property

    // bad
    foo [bar];
    foo. bar;
    foo .bar;
    foo. bar. baz;
    // good
    foo.bar;
    foo[bar];
    foo.bar.baz;
        .bar()
        .baz();
    
  • 行首逗号: 不需要。 eslint: comma-style
  • 额外的行末逗号:不需要。这样做会在 IE6/7 和 IE9 怪异模式下引起问题。 eslint: comma-dangle
  • 禁止使用多个逗号来声明一个空数组。 eslint: no-sparse-arrays
  • 避免使用逗号操作符,在for语句的初始化或更新部分或如果表达式序列明确地包含在括号中时可以使用逗号运算符。 eslint: no-sequences
  • JavaScript 的语句以分号作为结束符,禁止省略分号。 eslint: no-unexpected-multiline eslint: semi
  • 不允许使用多余的分号。 eslint: no-extra-semi
  • 变量的名称采用驼峰法则,首字母小写,后续单词的首字母大写。 eslint: camelcase

  • 总是使用 var 来声明变量。不这么做将导致产生全局变量。我们要避免污染全局命名空间。eslint:no-undef

  • 使用 var 声明每一个变量,并且每行只声明一个变量。这样做的好处是增加新变量将变的更加容易,而且你永远不用再担心调换错 ;,。 eslint: one-var eslint:one-var-declaration-per-line

  • 最后再声明未赋值的变量。当你需要引用前面的变量赋值时这将变的很有用。

  • 在作用域顶部声明变量。这将帮你避免变量声明提升相关的问题。保证在代码块的顶部声明变量。 eslint: no-inner-declarations eslint: vars-on-top

  • 禁止重复声明变量。 eslint: no-redeclar

  • 禁止修改全局对象或只读全局对象。 eslint: no-global-assign

  • 禁止在循环语句中编写函数。由于函数在循环周围创建闭包的方式,在循环中编写函数往往会导致错误。 eslint: no-loop-func

    // bad
    var data = [];
    for (var i = 10; i; i--) {
        data[i] = function() { return i; };
    data[0]();
    data[1]();
    data[2]();
    // good
    var itemFunc = function (t) { console.log(t) };
    for (var i = 10; i; i--) {
        itemFunc(i);
    

    禁止使用尤达条件,尤达条件语句就是对象字面量写在比较操作符的左边,而变量应该写在比较操作符的右边。 eslint: yoda

    // bad
    if ('red' === color) {
        // ...
    if (true === flag) {
        // ...
    if (5 > count) {
        // ...
    // good
    if (flag === true) {
        // ...
    if (value === 'red') {
        // ...
    
  • 禁止用delete删除var声明的变量,delete运算符的目的是从对象中删除属性。delete在变量上使用运算符可能会导致意外行为。 eslint: no-delete-var

  • 禁止创建与作用域内的变量共享名称的标签的不良做法。 eslint: no-label-var

  • 禁止声明的变量与外层作用域的变量同名。 eslint: no-shadow

  • 禁止声明变量时覆盖JavaScript中的保留关键字。eslint: no-shadow-restricted-names

  • 禁止使用没有定义的变量。 eslint: no-undef eslint: no-use-before-define

  • 禁止将变量初始化为undefined,在JavaScript中,声明但未初始化为任何值的变量会自动获取值undefined,因此不必将变量初始化为undefined。 eslint: no-undef-init

  • 不允许定义了的变量但是在后面的代码中没有被使用到。 eslint: no-unused-vars

  • 禁止使用链式赋值的表达式。 eslint: no-multi-assign

  • 使用直接量创建对象。 eslint: no-new-object

  • 在使用长方法链时进行缩进时,使用前面的点 . 强调这是方法调用而不是新语句。在使用.号调用对象属性时,应保持.号与属性在同一行。 eslint:dot-location eslint:newline-per-chained-call

    // bad
    $('#items').find('.selected').highlight().end().find('.open').updateCount();
    var foo = object.
            property;
    // bad
    $('#items').
        find('.selected').
        highlight().
        end().
        find('.open').
        updateCount();
    // good
    $('#items')
        .find('.selected')
        .highlight()
        .end()
        .find('.open')
        .updateCount();
    var foo = object.property;
    // bad
    var leds = stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led', true)
        .attr('width', (radius + margin) * 2).append('svg:g')
        .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
        .call(tron.led);
    // good
    var leds = stage.selectAll('.led')
        .data(data)
        .enter().append('svg:svg')
        .classed('led', true)
        .attr('width', (radius + margin) * 2)
        .append('svg:g')
        .attr('transform', 'translate(' + (radius + margin) + ',' + (radius + margin) + ')')
        .call(tron.led);
    
  • 不允许在使用对象字面量申明对象的时使用相同的键名。 eslint:no-dupe-keys

  • 禁止将全局对象(Math和JSON)作为函数调用。eslint:no-obj-calls

  • 禁止使用特定对象的指定方法,有arguments的callee方法、Math的pow方法。 eslint: no-restricted-properties

  • 不要使用保留字作为键名,它们在 IE8 下不工作。 eslint: no-shadow-restricted-names

  • 使用直接量创建数组。 禁止使用new创建包装实例,如 new String、new Number,这样会变成初始化一个对象,而不是对应的初始类型。eslint: no-new-wrappers

    // bad
    var items = new Array();
    // good
    var items = [];
    
  • 向数组增加元素时使用 Array#push 来替代直接赋值。

  • 当你需要拷贝数组时,使用 Array#slice。jsPerf

  • 使用 Array#slice 将类数组对象转换成数组。

    function trigger() {
        var args = Array.prototype.slice.call(arguments);
    
  • 禁止Array构造函数。eslint: no-array-constructor

  • 禁止使用for-in语句枚举数组。

    // bad
    var list = [8, 3, 11, 9, 6]
    for (i in list) {
        console.log(list[i]);
    // good
    var obj={
       one:'first',
       two:'zoo',
       three:'34'
    for (var key in obj) {
        if (Object.prototype.hasOwnProperty.call(obj, key)) {
            console.log(key+':'+obj[key]);
    

    永远不要在一个非函数代码块(if、while 等)中声明或赋值一个函数,浏览器允许你这么做,但它们的解析表现不一致,正确的做法是:在块外定义一个变量,然后将函数赋值给它。 eslint: no-inner-declarations

    // bad
    if (test) {
    function doSomething() { }
    function doSomethingElse() {
        if (test) {
            function doAnotherThing() { }
    // good
    function test() {
            console.log('Yup.');
    
  • 永远不要把参数命名为 arguments。这将取代函数作用域内的 arguments 对象。 eslint: no-shadow-restricted-names

  • 在函数中有分支时,保证所有的return 语句要么都指定返回值,要么都不指定返回值。 eslint: consistent-return

    // bad
    function doSomething(condition) {
        if (condition) {
            return true;
        } else {
            return;
    function doSomething(condition) {
        if (condition) {
            return true;
    // good
    function doSomething(condition) {
        if (condition) {
            return true;
        } else {
            return false;
    function Foo() {
        if (!(this instanceof Foo)) {
            return new Foo();
        this.index = 0;
    

    禁止出现空函数,如果一个函数包含了一条注释,它将不会被认为有问题,这里允许普通功能函数、对象文字的类方法和方法简写为空。 eslint: no-empty-function

    // good
    function foo() {}
    var foo = function() {};
    var obj = {
        foo: function() {}
    

    禁止给函数的参数重新赋值。主要原因有两点,一是对函数参数进行重新赋值操作后最后会搞不清函数参数的初始值,二是如果参数是引用类型的参数在函数内部对参数进行操作会也会同样影响到函数外部此参数的值。正确的做法是:如果函数不是引用类型可以在函数内部定义变量并将其赋值给该变量;如果参数为引用类型的参数,如果为对象类型则推荐使用fish的extend方法,如果是数组类型的推荐使用Array的slice方法。 eslint: no-param-reassign

    var test = 'test';
    var testObj = { item:'item' };
    var testArr = [1,2,3];
    // bad
    function foo(test) {
        test = 'abc';
    function foo(testObj) {
        testobj = { bar: 'abc' };
    // good
    function foo(test) {
        var bar = test;
    function foo(testObj) {
        var test = fish.extend({}, testObj);
    function foo(testArr) {
        var test = testArr.slice();
    
    // bad
    var testA = function () { return { y: 1 };}();
    var testB = (function () { return { y: 1 };})();
    // good
    var testA = (function () { return { y: 1 };}());
    
  • 不允许函数参数使用相同的参数名。 eslint: no-dupe-args

  • 使用函数声明书写的函数,不允许被重写或重新赋值。 eslint: no-func-assign

  • 在调用不带参的构造函数时必须加圆括号。 eslint: new-parens

  • 禁止不严格要求的函数属性名加引号。 eslint: quote-props

    // bad
    var object = {
        'a': 0,
        '0': 0,
        'true': 0,
        'null': 0
    // good
    var object1 = {
        'a-b': 0,
        '0x0': 0,
        '1e2': 0
    var object2 = {
        foo: 'bar',
        baz: 42,
        true: 0,
        0: 0,
        'qux-lorem': true
    
  • 直接通过属性名来访问对象属性时,使用 . 来访问对象的属性。 eslint: dot-notation

  • 当需要通过变量间接访问对象属性时使用中括号 []

  • 规定声明对象的属性时只能一行声明所有的属性或者每行声明一个属性。 eslint: object-property-newline

  • 禁止使用proto属性,proto属性已从ECMAScript 3.1开始弃用,不应在代码中使用,改用getPrototypeOf方法。 eslint: no-proto

    // bad
    var testA = obj.__proto__;
    var testB = obj['__proto__'];
    // good
    var testA = Object.getPrototypeOf(obj);
    

    iterator属性是JavaScript的SpiderMonkey扩展,可用于创建与JavaScript for in和for each构造兼容的自定义迭代器。但是,此属性现在已过时,因此不应使用它。 eslint: no-iterator

    // bad
    Foo.prototype.__iterator__ = function() {
        return new FooIterator(this);
    foo.__iterator__ = function () {};
    foo['__iterator__'] = function () {};
    
  • 使用 === 和 !==,禁止使用 == 和 !=。 eslint: eqeqeq

  • 条件表达式例如 if 语句通过抽象方法 ToBoolean 强制计算它们的表达式并且总是遵守下面的规则:

    对象 被计算为 true Undefined 被计算为 false Null 被计算为 false 布尔值 被计算为 布尔的值 数字 如果是 +0、-0 或 NaN 被计算为 false,否则为 true 字符串 如果是空字符串 '' 被计算为 false,否则为 true
    if ([0]) {
        // true
        // 一个数组就是一个对象,对象被计算为 true
    

    使用快捷方式。

    // bad
    if (name !== '') {
       // ...stuff...
    // good
    if (name) {
        // ...stuff...
    // bad
    if (collection.length > 0) {
        // ...stuff...
    // good
    if (collection.length) {
        // ...stuff...
    

    对于绝大多数的使用情况下,结果typeof操作是下列字符串常量之一:"undefined","object","boolean","number","string","function"和"symbol"。将typeof运算符的结果与其他字符串文字进行比较通常是代码编写出现错误。 eslint: valid-typeof

     //bad
    typeof foo === undefined;
    typeof bar === Object;
    typeof baz === 'strnig';
    typeof qux === 'some invalid type';
    typeof baz === anotherVariable;
    typeof foo === 5;
    //good
    typeof foo === 'undefined';
    typeof bar === 'object';
    typeof baz === 'string';
    typeof bar === typeof qux;
    
  • 避免出现与本身作比较的语句。 eslint: no-self-compare

  • 禁止对关系运算符的左操作数使用否定运算符。 eslint: no-unsafe-negation

  • 禁止使用位运算符。 eslint: no-bitwise

  • 禁止混合使用不同的运算符,如连续使用不带括号的不同运算符。用括号括起复杂的表达式可以清晰表达开发人员的意图,使代码更具可读性。 eslint: no-mixed-operators

    // bad
    var foo = a + b * c;
    // good
    var foo = a + (b * c);
    var foo = (a + b) * c;
    
  • 三元运算符禁止嵌套。 eslint: no-nested-ternary

  • 禁止使用没有必要的三元运算符。因为有些三元运算符可以直接使用其他语句替换。 eslint: no-unneeded-ternary

    // bad
    var test = x === 2 ? true : false;
    var test = x === 2 ? false : true;
    // good
    var test = x === 2;
    var test = x !== 2;
    
  • if、for等语句的执行语句部分无论多少句语句都要使用括号{}包裹(只有一句语句时也要使用{}包裹)。 eslint: curly

  • 如果通过 ifelse 使用多行代码块,把 else 放在 if 代码块关闭括号的同一行。 eslint: brace-style

    // bad
    if (test) {
        thing1();
        thing2();
    else {
        thing3();
    // good
    if (test) {
        thing1();
        thing2();
    } else {
        thing3();
    
  • 避免代码中出现空的代码块。 eslint: no-empty

  • 不允许重写通过catch代码块捕获到的错误。 eslint: no-ex-assign

    // bad
    try {
        // code
    } catch (e) {
        e = 10;
    // good
    try {
        // code
    } catch (e) {
        var foo = 10;
    
  • 禁止不必要的嵌套块。 eslint: no-lone-blocks

  • 禁止在 finally 语句块中出现控制流语句,如return,throw、break、continue块。它允许间接使用,例如在 function中定义。 eslint: no-unsafe-finally

    // bad
    var foo = function() {
        try {
            return 1;
        } catch(err) {
            return 2;
        } finally {
            return 3;
    // good
    var foo = function() {
        try {
            return 1;
        } catch(err) {
            return 2;
        } finally {
            console.log("hola!");
    

    此规则不允许将if语句作为else块中的唯一语句。如果if语句是else块中的唯一语句,则使用else if表单通常更清晰。 eslint: no-lonely-if

    // bad
    if (condition) {
        // ...
    } else {
        if (anotherCondition) {
            // ...
    if (condition) {
        // ...
    } else {
        if (anotherCondition) {
            // ...
        } else {
            // ...
    // good
    if (condition) {
        // ...
    } else if (anotherCondition) {
        // ...
    if (condition) {
        // ...
    } else if (anotherCondition) {
        // ...
    } else {
        // ...
    

    要求所有的switch语句都必须要有一个default分支,如果没有则需要有注释说明是开发人员不打算设置默认行为,否则将会检测报错。eslint: default-case

    // bad
    var test = 1;
    switch (test) {
        case 1:
            /* code */
            break;
    // good
    var testA = 1;
    var testB = 1;
    switch (testA) {
        case 1:
            /* code */
            break;
        default:
            /* code */
            break;
    switch (testB) {
        case 1:
            /* code */
            break;
        // no default
    

    保证在for-in 循环中使用了if 语句,注意只能遍历对象自身的属性,不能遍历原型链上的属性。 。 eslint: guard-for-in

    // bad
    for (key in foo) {
        console.log(key);
    // good
    for (key in foo) {
        if (Object.prototype.hasOwnProperty.call(foo, key)) {
            console.log(key);
    

    尽量不要在case/default语句中使用函数声明,如果要使用请确保函数声明仅适用于当前case子句,将子句使用{}包装在块中。 eslint: no-case-declarations

    // bad
    switch (foo) {
        case 1:
            function f() {}
            break;
        // no default
    // good
    switch (foo) {
        // The following case clauses are wrapped into blocks using brackets
        case 1: {
            function f() {}
            break;
        case 2:
            // Declarations using var without brackets are valid due to function-scope hoisting
            var z = 4;
            break;
        default: {
            /* code */
            break;
    

    禁止 if 语句中有 return 之后有 else,如果if块包含return语句,则该else块变得不必要,它的内容可以放在块外面。 eslint: no-else-return

    // bad
    function foo() {
        if (x) {
            return y;
        } else {
            return z;
    // good
    function foo() {
        if (x) {
            return y;
        return z;
    

    禁止不必要的 .bind() 调用,主要是出现在为函数参数绑定到了特定的对象,但是在你的函数体内并没有用到this值。 eslint: no-extra-bind

    // bad
    var boundGetName = (function getName() {
        return 'ESLint';
    }).bind(this);
    console.log(boundGetName());
    // good
    var boundGetName = (function getName() {
        return this.name;
    }).bind(this);
    console.log(boundGetName());
    var test = function () {
        return this.name;
    }.bind(this);
    console.log(test());
    
  • 禁用不必要的标签,如果循环不包含嵌套循环或开关,则不需要标记循环。您可以通过删除标签并使用break或continue不使用标签来获得相同的结果。eslint: no-extra-label

  • 禁止 case 语句落空,旨在消除一个case情况对另一个case情况的的无意破坏。 eslint: no-fallthrough

    // bad
    var foo = 1;
    function doSomething() {
        var bar = 1;
    switch (foo) {
        case 1:
            doSomething();
        case 2:
            doSomething();
    // good
    var foo = 1;
    function doSomething() {
        var bar = 1;
    switch (foo) {
        case 1:
            doSomething();
            break;
        case 2:
            doSomething();
            break;
        default: {
            /* code */
            break;
    
  • return 语句中不能有赋值表达式。eslint: no-return-assign

  • 禁止在代码中使用alert, confirm, and prompt, console, debugger。eslint: no-alert eslint: no-console eslint: no-debugger

  • 禁止在代码中使用 arguments.caller 或 arguments.callee,使用arguments.caller和arguments.callee进行多次代码优化是不可能的。它们在未来的JavaScript版本中已被弃用,并且在严格模式下禁止在ECMAScript 5中使用它们。 eslint: no-caller

  • 禁止在代码中使用eval()或者类似于eval()的方法,例如使用setTimeout(),setInterval()或者execScript()(仅限Internet Explorer),所有这些都可以接受一串JavaScript代码作为它们的第一个参数,这被认为是隐含的,eval()因为传入了一串JavaScript代码进行解释。所以对于这两个setTimeout()和setInterval()的第一个参数也可以是一个函数,并且被认为是更安全,更高性能。在链接地址中使用 javascript: 被有些人认为是 eval 的一种形式。在 javascript: 链接中的代码必须由浏览器解析和赋值,其处理方式与 eval 一样。 eslint: no-eval eslint: no-implied-eval eslint: no-script-url

    // bad
    var obj = { x: 'foo' };
    var key = 'x';
    var value = eval('obj.' + key);
    location.href = 'javascript:void(0)'; // 在链接地址中使用 javascript: 被认为是 eval 的一种形式。因为在 javascript: 链接中的代码必须由浏览器解析和赋值,其处理方式与 eval 一样
    setTimeout("alert('Hi!');", 100);
    setInterval("alert('Hi!');", 100);
    // good
    var obj = { x: 'foo' };
    var key = 'x';
    var value = obj[key];
    setTimeout(function () {
        alert('Hi!');
    }, 100);
    setInterval(function () {
        alert('Hi!');
    }, 100);
    

    禁止使用with语句,with语句可能存在问题,因为它将对象的成员添加到当前作用域,从而无法分辨块内的变量实际引用的内容。 eslint: no-with

    // bad
    with (point) {
        r = Math.sqrt(x * x + y * y); // is r a member of point?
    
  • 禁止自我赋值。 eslint: no-self-assign

  • 禁止使用八进制数字和八进制的转义序列。eslint: no-octal eslint: no-octal-escape

    // bad
    var num = 071;
    var result = 5 + 07;
    // good
    var num = '0x39';
    
  • 代码中禁止出现没有被使用到的表达式、值或标签,常见比如短路表达式是不允许使用的。eslint: no-unused-expressions eslint: no-unused-labels

  • 禁止不必要的转义。 eslint: no-useless-escape

    // bad
    "\'";
    '\"';
    '\#';
    '\e';
    // good
    '\'';
    '\\';
    '\n';
    
  • 禁止没有必要的return(后面没有语句了)。 eslint: no-useless-return

  • 规定单行最大长度为150。eslint: max-len

  • 13.注释

  • 让注释有意义。重点在解释那些不容易立即明白的逻辑上。不要把读者的时间浪费在阅读类似于: i = 0; // 让i 等于0

  • 函数头注释 使用 /** ... */ 作为多行注释。包含描述、指定所有参数和返回值的类型和值。

    // 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;
    

    使用 // 作为单行注释。在注释对象上面另起一行使用单行注释。并且在块注释前要插入空行。 eslint: lines-around-comment

    // bad
    function getType() {
        console.log('fetching type...'); // This is console.
        /* set the default type to 'no type'*/
        var type = 'no type';
        return type;
    // good
    function getType() {
        // This is console.
        console.log('fetching type...');
        /* set the default type to 'no type'*/
        var type = 'no type';
        return type;
    

    给注释增加 FIXMETODO 的前缀可以帮助其他开发者快速了解这是一个需要复查的问题,或是给需要实现的功能提供一个解决方式。这将有别于常见的注释,因为它们是可操作的,通过检测后对代码相应的注释处将会发出警告。使用 FIXME -- need to figure this out 或者 TODO -- need to implement。 eslint: no-warning-comments

    function Calculator() {
        // FIXME: shouldn't use a global here
        total = 0;
        return this;
    

    给对象原型分配方法,而不是使用一个新对象覆盖原型。覆盖原型将导致继承出现问题:重设原型将覆盖原有原型!

    function Jedi() {
        console.log('new jedi');
    // bad
    Jedi.prototype = {
        fight: function fight() {
            console.log('fighting');
        block: function block() {
            console.log('blocking');
    // good
    Jedi.prototype.fight = function fight() {
        console.log('fighting');
    Jedi.prototype.block = function block() {
        console.log('blocking');
    

    当给事件附加数据时(无论是 DOM 事件还是私有事件),传入一个对象而不是原始值。这样可以让后面的贡献者增加更多数据到事件数据而无需找出并更新事件的每一个处理器。例如,不好的写法:

    // bad
    $(this).trigger('listingUpdated', listing.id);
    $(this).on('listingUpdated', function (e, listingId) {
        // do something with listingId
    

    更好的写法:

    // good
    $(this).trigger('listingUpdated', { listingId : listing.id });
    $(this).on('listingUpdated', function (e, data) {
        // do something with data.listingId