ES6的十二个新特色,本身征集的做事js库
分类:前端技术

30分钟ES6从陌生到熟悉

2018/07/30 · JavaScript · es6

原文出处: 叶小钗   

js中的异步是指一个函数在执行过程中,其中一部分不能马上执行完毕,然后执行函数体中另外一部分。等到第一部分得到返回值再执行第二部分。

1.回调函数callback

无法捕获错误 try catch

不能return

回调地狱

  function personInfo(callback){

    $.ajax({

          type: "GET",

          url: "test.json", 

          data: {

                username:username,

                content:content

          },

        dataType: "json",

        success: function(data){

              if(data.length>0){

                    callback&&callback();

              }

        }

  });

}

2.事件发布/订阅模型

给一个事件,订阅几个方法,方法依次执行。

function Event() {

    this.event = {};

}

Event.prototype.on = function (type,callBack) {

    if(this.event[type]){

        this.event[type].push(callBack);

    }else{

        this.event[type] = [callBack];

    }

};

Event.prototype.emit = function (type,...data) {

    this.event[type].forEach((item)=>item(...data));

};

let event = new Event();

function fn1(){

  console.log('吃饭');

}

function fn2(){

    console.log('工作');

}

event.on('我的一天',fn1);

event.on('我的一天',fn2);

event.emit('我的一天');

3.Promise异步函数解决方案

  A执行完执行B,B执行完执行C。把A的返回值给B再给C

每一次执行,返回一个新的Promise实例(链式调用)

  代码易读

let p1 = new Promise(function(resolve,reject){

  reject(10000000);

});

p1.then(function(value){

  console.log('成功1=',value);

},function(reason){

  console.log('失败1=',reason);

});

p1.then(function(value){

  console.log('成功2=',value);

},function(reason){

  console.log('失败2=',reason);

});

4.Generator生成器函数

调用一个生成器函数它不会立刻执行

它返回一个迭代器函数,每调用一次next就可以返回一个值对象

function *go(a){

    console.log(1);

    let b =  yield a;

    console.log(2);

    let c = yield b;

    console.log(3);

    return c;

}

let it = go("a值");

let r1 = it.next();

let r2 = it.next('B值');

5.Co

co是一个为Node.js和浏览器打造的基于生成器的流程控制工具,借助于Promise,你可以使用更加优雅的方式编写非阻塞代码。

let fs = require('fs');

function readFile(filename) {

  return new Promise(function (resolve, reject) {

    fs.readFile(filename, function (err, data) {

      if (err)

        reject(err);

      else

        resolve(data);

    })

  })

}

function *read() {

  let template = yield readFile('./template.txt');

  let data = yield readFile('./data.txt');

  return template ' ' data;

}

co(read).then(function (data) {

  console.log(data);

}, function (err) {

  console.log(err);

});

function co(gen) {

  let it = gen();

  return new Promise(function (resolve, reject) {

    !function next(lastVal) {

      let {value, done} = it.next(lastVal);

      if (done) {

        resolve(value);

      } else {

        value.then(next, reason => reject(reason));

      }

    }();

  });

}

6.Async/ await

可以实现和co一样的功能

结构简单,可读性强

let fs = require('fs');

function readFile(filename) {

*  return new Promise(function (resolve, reject) {*

*    fs.readFile(filename, 'utf8', function (err, data) {*

*      if (err)*

*        reject(err);*

*      else*

*        resolve(data);*

*    })*

*  })*

}

async function read() {

*  let template = await readFile('./template.txt');*

*  let data = await readFile('./data.txt');*

*  return template ' ' data;*

}

let result = read();

result.then(data=>console.log(data));

今年工作进度到这里结束,整理一下今年收集的自用js库,后期会更新,代码已贴github=>

这里只讲 ES6比较突出的特性,因为只能挑出十个,所以其他特性请参考官方文档;

前言

ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

这句话基本涵盖了为什么会产生ES6这次更新的原因——编写复杂的大型应用程序。

回顾近两年的前端开发,复杂度确实在快速增加,近期不论从系统复杂度还是到前端开发人员数量应该达到了一个饱和值,换个方式说,没有ES6我们的前端代码依旧可以写很多复杂的应用,而ES6的提出更好的帮我们解决了很多历史遗留问题,另一个角度ES6让JS更适合开发大型应用,而不用引用太多的库了。

本文,简单介绍几个ES6核心概念,个人感觉只要掌握以下新特性便能愉快的开始使用ES6做代码了!

这里的文章,请配合着阮老师这里的教程,一些细节阮老师那边讲的好得多:

除了阮老师的文章还参考:

PS:文中只是个人感悟,有误请在评论提出

  

/**
 * Created by zhangsong on 16/5/20.
 */
//    ***********Number One : Parameters************
//                   参数的传递
//ES5:
var link = function (height,color,url) {
  var height = height || 50;
  var color = color || 'red';
  var url = url || ''
};

模块Module的引入

都说了复杂的大型应用了,所以我们第一个要讨论的重要特性就是模块概念,我们做一个复杂的项目必定需要两步走:

① 分得开,并且需要分开

② 合得起来

我们普遍认为没有复杂的应用,只有分不开的应用,再复杂的应用,一旦可以使用组件化、模块化的方式分成不同的小单元,那么其难度便会大大降低,模块化是大型、复杂项目的主要拦路虎。为了解决这个问题,社区制定了一些模块加载方案,对于浏览器开发来说,我们用的最多的是AMD规范,也就是大家熟知的requireJS,而ES6中在语音标准层面实现了模块功能,用以取代服务端通信的CommonJS和AMD规范,成为了通用的规范,多说无益,我们这里上一段代码说明:

/* validate.js 多用于表单验证 */ export function isEmail (text) { var reg = /^(([^<>()[]\.,;:s@"] (.[^<>()[]\.,;:s@"] )*)|(". "))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9] .) [a-zA-Z]{2,}))$/; return reg.test(text); } export function isPassword (text) { var reg = /^[a-zA-Z0-9]{6,20}$/; return reg.test(text); }

1
2
3
4
5
6
7
8
9
10
11
12
/*
validate.js 多用于表单验证
*/
export function isEmail (text) {
    var reg = /^(([^<>()[]\.,;:s@"] (.[^<>()[]\.,;:s@"] )*)|(". "))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9] .) [a-zA-Z]{2,}))$/;
    return reg.test(text);
}
 
export function  isPassword (text) {
    var reg = /^[a-zA-Z0-9]{6,20}$/;
    return reg.test(text);
}

那么我们现在想在页面里面使用这个工具类该怎么做呢:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!-- 请注意这里type=module才能运行 --> <script type="module"> import {isEmail} from './validate.js'; var e1 = 'dddd'; var e2 = 'yexiaochai@qq.com' console.log(isEmail(e1)) console.log(isEmail(e2)) </script> </body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!-- 请注意这里type=module才能运行 -->
<script type="module">
    import {isEmail} from './validate.js';
    var e1 = 'dddd';
    var e2 = 'yexiaochai@qq.com'
    console.log(isEmail(e1))
    console.log(isEmail(e2))
</script>
</body>
</html>

ES6中的Module提出,在我这里看来是想在官方完成之前requireJS干的工作,这里也有一些本质上的不一样:

① requireJS是使用加载script标签的方式载入js,没有什么限制

② import命令会被js引擎静态分析,先于模块其他语句执行

以上特性会直接给我们带来一些困扰,比如原来我们项目控制器会有这么一段代码:

var viewId = ''; //由浏览器获取试图id,url可能为?viewId=booking|list|... //如果不存在则需要构建,记住构建时需要使用viewdata继承源view requirejs(viewId, function(View) { //执行根据url参数动态加载view逻辑 })

1
2
3
4
5
var viewId = ''; //由浏览器获取试图id,url可能为?viewId=booking|list|...
//如果不存在则需要构建,记住构建时需要使用viewdata继承源view
requirejs(viewId, function(View) {
    //执行根据url参数动态加载view逻辑
})

前面说过了,import命令会被js引擎静态分析,先于模块其他语句执行,所以我们在根本不能将import执行滞后,或者动态化,做不到的,这种写法也是报错的:

if (viewId) { import view from './' viewId; }

1
2
3
if (viewId) {
  import view from './' viewId;
}

图片 1

这种设计会有利于提高编译器效率,但是之前的动态业务逻辑就不知道如何继续了?而ES6如果提供import的方法,我们变可以执行逻辑:

import(viewId, function() { //渲染页面 })

1
2
3
import(viewId, function() {
    //渲染页面
})

事实上他也提供了:

图片 2

现在看起来,JS中的模块便十分完美了,至于其中一些细节,便可以用到的时候再说了

/**

//ES6
var link = function(height = 50, color = 'red', url = 'azat.co'){

ES6中的类Class

我们对我们的定位一直是非常清晰的,我们就是要干大项目的,我们是要干复杂的项目,除了模块概念,类的概念也非常重要,我们之前用的这种方式实现一个类,我们来温故而知新。

当一个函数被创建时,Function构造函数产生的函数会隐式的被赋予一个prototype属性,prototype包含一个constructor对象

而constructor便是该新函数对象(constructor意义不大,但是可以帮我们找到继承关系)

每个函数都会有一个prototype属性,该属性指向另一对象,这个对象包含可以由特定类型的所有实例共享的属性和方法

每次实例化后,实例内部都会包含一个[[prototype]](__proto__)的内部属性,这个属性指向prototype

① 我们通过isPrototypeOf来确定某个对象是不是我的原型 ② hasOwnPrototype 可以检测一个属性是存在实例中还是原型中,该属性不是原型属性才返回true

1
2
① 我们通过isPrototypeOf来确定某个对象是不是我的原型
② hasOwnPrototype 可以检测一个属性是存在实例中还是原型中,该属性不是原型属性才返回true

var Person = function (name, age) { this.name = name; this.age = age; }; Person.prototype.getName = function () { return this.name; }; var y = new Person('叶小钗', 30);

1
2
3
4
5
6
7
8
var Person = function (name, age) {
    this.name = name;
    this.age = age;
};
Person.prototype.getName = function () {
    return this.name;
};
var y = new Person('叶小钗', 30);

图片 3

为了方便,使用,我们做了更为复杂的封装:

var arr = []; var slice = arr.slice; function create() { if (arguments.length == 0 || arguments.length > 2) throw '参数错误'; var parent = null; //将参数转换为数组 var properties = slice.call(arguments); //如果第一个参数为类(function),那么就将之取出 if (typeof properties[0] === 'function') parent = properties.shift(); properties = properties[0]; function klass() { this.initialize.apply(this, arguments); } klass.superclass = parent; klass.subclasses = []; if (parent) { var subclass = function () { }; subclass.prototype = parent.prototype; klass.prototype = new subclass; parent.subclasses.push(klass); } var ancestor = klass.superclass && klass.superclass.prototype; for (var k in properties) { var value = properties[k]; //满足条件就重写 if (ancestor && typeof value == 'function') { var argslist = /^s*functions*(([^()]*?))s*?{/i.exec(value.toString())[1].replace(/s/i, '').split(','); //只有在第一个参数为$super情况下才需要处理(是否具有重复方法需要用户自己决定) if (argslist[0] === '$super' && ancestor[k]) { value = (function (methodName, fn) { return function () { var scope = this; var args = [function () { return ancestor[methodName].apply(scope, arguments); } ]; return fn.apply(this, args.concat(slice.call(arguments))); }; })(k, value); } } klass.prototype[k] = value; } if (!klass.prototype.initialize) klass.prototype.initialize = function () { }; klass.prototype.constructor = klass; return klass; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
var arr = [];
var slice = arr.slice;
 
function create() {
  if (arguments.length == 0 || arguments.length > 2) throw '参数错误';
 
  var parent = null;
  //将参数转换为数组
  var properties = slice.call(arguments);
 
  //如果第一个参数为类(function),那么就将之取出
  if (typeof properties[0] === 'function')
    parent = properties.shift();
  properties = properties[0];
 
  function klass() {
    this.initialize.apply(this, arguments);
  }
 
  klass.superclass = parent;
  klass.subclasses = [];
 
  if (parent) {
    var subclass = function () { };
    subclass.prototype = parent.prototype;
    klass.prototype = new subclass;
    parent.subclasses.push(klass);
  }
 
  var ancestor = klass.superclass && klass.superclass.prototype;
  for (var k in properties) {
    var value = properties[k];
 
    //满足条件就重写
    if (ancestor && typeof value == 'function') {
      var argslist = /^s*functions*(([^()]*?))s*?{/i.exec(value.toString())[1].replace(/s/i, '').split(',');
      //只有在第一个参数为$super情况下才需要处理(是否具有重复方法需要用户自己决定)
      if (argslist[0] === '$super' && ancestor[k]) {
        value = (function (methodName, fn) {
          return function () {
            var scope = this;
            var args = [function () {
              return ancestor[methodName].apply(scope, arguments);
            } ];
            return fn.apply(this, args.concat(slice.call(arguments)));
          };
        })(k, value);
      }
    }
 
    klass.prototype[k] = value;
  }
 
  if (!klass.prototype.initialize)
    klass.prototype.initialize = function () { };
 
  klass.prototype.constructor = klass;
 
  return klass;
}

View Code

这里写一个demo:

var AbstractView = create({ initialize: function (opts) { opts = opts || {}; this.wrapper = opts.wrapper || $('body'); //事件集合 this.events = {}; this.isCreate = false; }, on: function (type, fn) { if (!this.events[type]) this.events[type] = []; this.events[type].push(fn); }, trigger: function (type) { if (!this.events[type]) return; for (var i = 0, len = this.events[type].length; i < len; i ) { this.events[type][i].call(this) } }, createHtml: function () { throw '必须重写'; }, create: function () { this.root = $(this.createHtml()); this.wrapper.append(this.root); this.trigger('onCreate'); this.isCreate = true; }, show: function () { if (!this.isCreate) this.create(); this.root.show(); this.trigger('onShow'); }, hide: function () { this.root.hide(); } }); var Alert = create(AbstractView, { createHtml: function () { return '<div class="alert">这里是alert框</div>'; } }); var AlertTitle = create(Alert, { initialize: function ($super) { this.title = ''; $super(); }, createHtml: function () { return '<div class="alert"><h2>' this.title '</h2>这里是带标题alert框</div>'; }, setTitle: function (title) { this.title = title; this.root.find('h2').html(title) } }); var AlertTitleButton = create(AlertTitle, { initialize: function ($super) { this.title = ''; $super(); this.on('onShow', function () { var bt = $('<input type="button" value="点击我" />'); bt.click($.proxy(function () { alert(this.title); }, this)); this.root.append(bt) }); } }); var v1 = new Alert(); v1.show(); var v2 = new AlertTitle(); v2.show(); v2.setTitle('我是标题'); var v3 = new AlertTitleButton(); v3.show(); v3.setTitle('我是标题和按钮的alert');

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
var AbstractView = create({
  initialize: function (opts) {
    opts = opts || {};
    this.wrapper = opts.wrapper || $('body');
 
    //事件集合
    this.events = {};
 
    this.isCreate = false;
 
  },
  on: function (type, fn) {
    if (!this.events[type]) this.events[type] = [];
    this.events[type].push(fn);
  },
  trigger: function (type) {
    if (!this.events[type]) return;
    for (var i = 0, len = this.events[type].length; i < len; i ) {
      this.events[type][i].call(this)
    }
  },
  createHtml: function () {
    throw '必须重写';
  },
  create: function () {
    this.root = $(this.createHtml());
    this.wrapper.append(this.root);
    this.trigger('onCreate');
    this.isCreate = true;
  },
  show: function () {
    if (!this.isCreate) this.create();
    this.root.show();
    this.trigger('onShow');
  },
  hide: function () {
    this.root.hide();
  }
});
 
var Alert = create(AbstractView, {
 
  createHtml: function () {
    return '<div class="alert">这里是alert框</div>';
  }
});
 
var AlertTitle = create(Alert, {
  initialize: function ($super) {
    this.title = '';
    $super();
 
  },
  createHtml: function () {
    return '<div class="alert"><h2>' this.title '</h2>这里是带标题alert框</div>';
  },
 
  setTitle: function (title) {
    this.title = title;
    this.root.find('h2').html(title)
  }
 
});
 
var AlertTitleButton = create(AlertTitle, {
  initialize: function ($super) {
    this.title = '';
    $super();
 
    this.on('onShow', function () {
      var bt = $('<input type="button" value="点击我" />');
      bt.click($.proxy(function () {
        alert(this.title);
      }, this));
      this.root.append(bt)
    });
  }
});
 
var v1 = new Alert();
v1.show();
 
var v2 = new AlertTitle();
v2.show();
v2.setTitle('我是标题');
 
var v3 = new AlertTitleButton();
v3.show();
v3.setTitle('我是标题和按钮的alert');

图片 4

ES6中直接从标准层面解决了我们的问题,他提出了Class关键词让我们可以更好的定义类,我们这里用我们ES6的模块语法重新实现一次:

export class AbstractView { constructor(opts) { opts = opts || {}; this.wrapper = opts.wrapper || $('body'); //事件集合 this.events = {}; this.isCreate = false; } on(type, fn) { if (!this.events[type]) this.events[type] = []; this.events[type].push(fn); } trigger(type) { if (!this.events[type]) return; for (var i = 0, len = this.events[type].length; i < len; i ) { this.events[type][i].call(this) } } createHtml() { throw '必须重写'; } create() { this.root = $(this.createHtml()); this.wrapper.append(this.root); this.trigger('onCreate'); this.isCreate = true; } show() { if (!this.isCreate) this.create(); this.root.show(); this.trigger('onShow'); } hide() { this.root.hide(); } } export class Alert extends AbstractView { createHtml() { return '<div class="alert">这里是alert框</div>'; } } export class AlertTitle extends Alert { constructor(opts) { super(opts); this.title = ''; } createHtml() { return '<div class="alert"><h2>' this.title

  • '</h2>这里是带标题alert框</div>'; } setTitle(title) { this.title = title; this.root.find('h2').html(title) } } export class AlertTitleButton extends AlertTitle { constructor(opts) { super(opts); this.on('onShow', function () { var bt = $('<input type="button" value="点击我" />'); bt.click($.proxy(function () { alert(this.title); }, this)); this.root.append(bt) }); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
export class AbstractView {
    constructor(opts) {
        opts = opts || {};
        this.wrapper = opts.wrapper || $('body');
        //事件集合
        this.events = {};
        this.isCreate = false;
    }
    on(type, fn) {
        if (!this.events[type]) this.events[type] = [];
        this.events[type].push(fn);
    }
    trigger(type) {
        if (!this.events[type]) return;
        for (var i = 0, len = this.events[type].length; i < len; i ) {
            this.events[type][i].call(this)
        }
    }
    createHtml() {
        throw '必须重写';
    }
    create() {
        this.root = $(this.createHtml());
        this.wrapper.append(this.root);
        this.trigger('onCreate');
        this.isCreate = true;
    }
    show() {
        if (!this.isCreate) this.create();
        this.root.show();
        this.trigger('onShow');
    }
    hide() {
        this.root.hide();
    }
}
export class Alert extends AbstractView {
    createHtml() {
        return '<div class="alert">这里是alert框</div>';
    }
}
export class AlertTitle extends Alert {
    constructor(opts) {
        super(opts);
        this.title = '';
    }
    createHtml() {
        return '<div class="alert"><h2>' this.title '</h2>这里是带标题alert框</div>';
    }
    setTitle(title) {
        this.title = title;
        this.root.find('h2').html(title)
    }
}
export class  AlertTitleButton extends AlertTitle {
    constructor(opts) {
        super(opts);
        this.on('onShow', function () {
            var bt = $('<input type="button" value="点击我" />');
            bt.click($.proxy(function () {
                alert(this.title);
            }, this));
            this.root.append(bt)
        });
    }
}

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script type="text/javascript" src="zepto.js"></script> <!-- 请注意这里type=module才能运行 --> <script type="module"> import {Alert, AlertTitle, AlertTitleButton} from './es6class.js'; var v1 = new Alert(); v1.show(); var v2 = new AlertTitle(); v2.show(); v2.setTitle('我是标题'); var v3 = new AlertTitleButton(); v3.show(); v3.setTitle('我是标题和按钮的alert'); </script> </body> </html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script type="text/javascript" src="zepto.js"></script>
 
<!-- 请注意这里type=module才能运行 -->
<script type="module">
import {Alert, AlertTitle, AlertTitleButton} from './es6class.js';
var v1 = new Alert();
v1.show();
var v2 = new AlertTitle();
v2.show();
v2.setTitle('我是标题');
var v3 = new AlertTitleButton();
v3.show();
v3.setTitle('我是标题和按钮的alert');
</script>
</body>
</html>

这里的代码完成了与上面一样的功能,而代码更加的清爽了。

* @param {long} //通用函数库

};

ES6中的函数

我们这里学习ES6,由大到小,首先讨论模块,其次讨论类,这个时候理所当然到了我们的函数了,ES6中函数也多了很多新特性或者说语法糖吧,首先我们来说一下这里的箭头函数

* @param {onerror} //js错误调试

            //Number Two : Template Literals
//                  字面量插入字符串
//ES5

箭头函数

//ES5 $('#bt').click(function (e) { //doing something }) //ES6 $('#bt').click(e => { //doing something })

1
2
3
4
5
6
7
8
//ES5
$('#bt').click(function (e) {
    //doing something
})
//ES6
$('#bt').click(e => {
    //doing something
})

有点语法糖的感觉,有一个很大不同的是,箭头函数不具有this属性,箭头函数直接使用的是外部的this的作用域,这个想不想用看个人习惯吧。

* @author lpg 2017-11-02

var name = 'your name is'   first   ''   last   '.';
var url =  ''   id ;

参数新特性

ES6可以为参数提供默认属性

function log(x, y = 'World') { console.log(x, y); } log('Hello') // Hello World log('Hello', 'China') // Hello China log('Hello', '') // Hello

1
2
3
4
5
6
7
function log(x, y = 'World') {
  console.log(x, y);
}
 
log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello

至于不定参数撒的,我这里没有多过多的使用,等项目遇到再说吧,如果研究的太细碎,反而不适合我们开展工作。

*/

//ES6

let、const和var

之前的js世界里,我们定义变量都是使用的var,别说还真挺好用的,虽有会有一些问题,但是对于熟悉js特性的小伙伴都能很好的解决,一般记住:变量提升会解决绝大多数问题。

就能解决很多问题,而且真实项目中,我们会会避免出现变量出现重名的情况所以有时候大家面试题中看到的场景在实际工作中很少发生,只要不刻意臆想、制造一些难以判断的场景,其实并不会出现多少BUG,不能因为想考察人家对语言特性的了解,就做一些容易容易忘掉的陷阱题。

无论如何,var 声明的变量受到了一定诟病,事实上在强类型语言看来也确实是设计BUG,但是完全废弃var的使用显然不是js该做的事情,这种情况下出现了let关键词。

let与var一致用以声明变量,并且一切用var的地方都可以使用let替换,新的标准也建议大家不要再使用var了,let具有更好的作用域规则,也许这个规则是边界更加清晰了:

{ let a = 10; var b = 1; } a // ReferenceError: a is not defined. b // 1

1
2
3
4
5
6
7
{
  let a = 10;
  var b = 1;
}
 
a // ReferenceError: a is not defined.
b // 1

这里是一个经典的闭包问题:

var a = []; for (var i = 0; i < 10; i ) { a[i] = function () { console.log(i); }; } a[6](); // 10

1
2
3
4
5
6
7
var a = [];
for (var i = 0; i < 10; i ) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 10

因为i在全局范围有效,共享同一个作用域,所以i就只有10了,为了解决这个问题,我们之前会引入闭包,产生新的作用域空间(好像学名是变量对象,我给忘了),但是那里的i跟这里的i已经不是一个东西了,但如果将var改成let,上面的答案是符合预期的。可以简单理解为每一次“{}”,let定义的变量都会产生新的作用域空间,这里产生了循环,所以每一次都不一样,这里与闭包有点类似是开辟了不同的空间。

for (let i = 0; i < 3; i ) { let i = 'abc'; console.log(i); } // abc // abc // abc

1
2
3
4
5
6
7
for (let i = 0; i < 3; i ) {
  let i = 'abc';
  console.log(i);
}
// abc
// abc
// abc

这里因为内部重新声明了i,事实上产生了3个作用域,这里一共有4个作用域指向,let最大的作用就是js中块级作用域的存在,并且内部的变量不会被外部所访问,所以之前为了防止变量侮辱的立即执行函数,似乎变得不是那么必要了。

之前我们定义一个常量会采用全部大写的方式:

var NUM = 10;

1
var NUM = 10;

为了解决这个问题,ES6引入了const命令,让我们定义只读常量,这里不对细节做过多研究,直接后续项目实践吧,项目出真知。

window.onerror = function (errorMessage, scriptURI, lineNumber, columnNumber, errorObj) {

var name = `your name is ${first} ${last}.`;
var url = `) ${id}`;

生成器Generators

ES6中提出了生成器Generators的概念,这是一种异步编程的解决方案,可以将其理解为一种状态机,封装了多个内部状态,这里来个demo:

function* helloWorldGenerator() { yield 'hello'; yield 'world'; return 'ending'; } var hw = helloWorldGenerator(); hw.next() // { value: 'hello', done: false } hw.next() // { value: 'world', done: false } hw.next() // { value: 'ending', done: true } hw.next() // { value: undefined, done: true }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function* helloWorldGenerator() {
  yield 'hello';
  yield 'world';
  return 'ending';
}
var hw = helloWorldGenerator();
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }

这个yield(产出)类似于之前的return,直观的理解就是一个函数可以返回多次了,或者说函数具有“顺序状态”,yield提供了暂停功能。这里我想写个代码来验证下期中的作用域状态:

function* test(){ let i = 0; setTimeout(function() { i ; }, 1000); yield i; yield i ; return i } let t = test(); console.log(t.next()); setTimeout(function() { console.log(t.next()); }, 2000); console.log(t.next()); //{value: 0, done: false} //{value: 0, done: false} //{value: 2, done: true}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function* test(){
    let i = 0;
    setTimeout(function() {
        i ;
    }, 1000);
    yield i;
    yield i ;
    return i
}
 
let t = test();
console.log(t.next());
 
setTimeout(function() {
    console.log(t.next());
}, 2000);
console.log(t.next());
 
//{value: 0, done: false}
//{value: 0, done: false}
//{value: 2, done: true}

之前我们写一个城市级联的代码,可能会有些令人蛋疼:

$.get('getCity', {id: 0}, function(province) { let pid = province[0]; //根据省id获取城市数据 $.get('getCity', {id: pid}, function(city) { let cityId = city[0]; //根据市级id获取县 $.get('getCity', {id: cityId}, function(city) { //do smt. }); }); });

1
2
3
4
5
6
7
8
9
10
11
$.get('getCity', {id: 0}, function(province) {
    let pid = province[0];
    //根据省id获取城市数据
    $.get('getCity', {id: pid}, function(city) {
        let cityId = city[0];
        //根据市级id获取县
        $.get('getCity', {id: cityId}, function(city) {
            //do smt.
        });
    });
});

这个代码大家应当比较熟悉了,用promise能从语法层面解决一些问题,这里简单介绍下promise。

console.log("错误信息:", errorMessage);

            //Number Three : Multi-line Strings
            //多行字符串
//ES5

Promise

Promise是一种异步解决方案,有些同事认为其出现就是为了我们代码变得更好看,解决回调地狱的语法糖,ES6将其写入了语音标准,提供了原生Promise对象。Promise为一容器,里面保存异步事件的结果,他是一个对象具有三个状态:pending(进行中)、fulfilled(已成功)、rejected(已失败),这里还是来个简单代码说明:

function timeout(ms) { return new Promise((resolve, reject) => { setTimeout(resolve, ms, 'done'); }); } timeout(100).then((value) => { console.log(value); });

1
2
3
4
5
6
7
8
9
function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'done');
  });
}
 
timeout(100).then((value) => {
  console.log(value);
});

实例化Promise时,第一个回调必须提供,是进行转为成功时候会执行,第二个也是一个函数失败时候调用,非必须,这里来个demo:

let timeout = function (ms) { return new Promise(function (resolve) { setTimeout(resolve, ms); }); }; timeout(1000).then(function () { return timeout(1000).then(function () { let s = '大家'; console.log(s) return s; }) }).then(function (data) { return timeout(1000).then(function () { let s = data '好,'; console.log(s) return s; }) }).then(function(data) { return timeout(1000).then(function () { let s = data '我是叶小钗'; console.log(s) return s; }); }).then(function(data) { console.log(data) });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
let  timeout = function (ms) {
    return new Promise(function (resolve) {
        setTimeout(resolve, ms);
    });
};
 
timeout(1000).then(function () {
    return timeout(1000).then(function () {
        let s = '大家';
        console.log(s)
        return s;
    })
 
}).then(function (data) {
    return timeout(1000).then(function () {
        let s = data '好,';
        console.log(s)
        return s;
    })
}).then(function(data) {
    return timeout(1000).then(function () {
        let s = data '我是叶小钗';
        console.log(s)
        return s;
    });
}).then(function(data) {
    console.log(data)
});

如果我们请求有依赖的话,第一个请求依赖于第二个请求,代码就可以这样写:

let getData = function(url, param) { return new Promise(function (resolve) { $.get(url, param, resolve ); }); } getData(' (data) { console.log('我获取了省数据,我们马上根据省数据申请市数据', data); return getData(' (data1) { console.log(data1); return '我是市数据'; }) }).then(function(data) { //前面的参数传过来了 console.log(data); console.log('我获取了市数据,我们马上根据市数据申请县数据'); getData(' (data1) { console.log(data1); }); })

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let getData = function(url, param) {
    return new Promise(function (resolve) {
        $.get(url, param, resolve );
    });
}
getData('http://api.kuai.baidu.com/city/getstartcitys?callback=?').then(function (data) {
    console.log('我获取了省数据,我们马上根据省数据申请市数据', data);
    return getData('http://api.kuai.baidu.com/city/getstartcitys?callback=?').then(function (data1) {
        console.log(data1);
        return '我是市数据';
    })
 
}).then(function(data) {
    //前面的参数传过来了
    console.log(data);
    console.log('我获取了市数据,我们马上根据市数据申请县数据');
    getData('http://api.kuai.baidu.com/city/getstartcitys?callback=?').then(function (data1) {
        console.log(data1);
    });
})

图片 5

如此便可以避免多层嵌套了,关于Promise的知识点还很多,我们遇到复杂的工作场景再拿出来说吧,我对他的定位就是一个语法糖,将异步的方式变成同步的写法,骨子里还是异步,上面我们用Promise解决回调地狱问题,但是回调地狱问题遇到的不多,却发现Promise一堆then看见就有点烦,我们的Generator函数似乎可以让这个情况得到缓解。

但是暂时在实际工作中我没有找到更好的使用场景,这里暂时到这里,后面工作遇到再详述,对这块不是很熟悉也不妨碍我们使用ES6写代码。

console.log("出错文件:", scriptURI);

var str = 'aaaaaaaaaaaaaaaaa'
    'bbbbbbbbbbbbbbbbbbbbbb'
    'cccccccccccccccccccccc';

代理

代理,其实就是你要做什么我帮你做了就行了,一般代理的原因都是,我需要做点手脚,或者多点操作,或者做点“赋能”,如我们常常包装setTimeout一般:

let timeout = function (ms, callback) { setTimeout(callback, ms); }

1
2
3
let timeout = function (ms, callback) {
    setTimeout(callback, ms);
}

我们包装setTimeout往往是为了clearTimeout的时候能全部清理掉,其实就是拦截下,ES6提供了Proxy关键词用于设置代理器:

var obj = new Proxy({}, { get: function (target, key, receiver) { console.log(`getting ${key}!`); return Reflect.get(target, key, receiver); }, set: function (target, key, value, receiver) { console.log(`setting ${key}!`); return Reflect.set(target, key, value, receiver); } }); obj.count = 1 // setting count! obj.count // getting count! // setting count! // 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var obj = new Proxy({}, {
  get: function (target, key, receiver) {
    console.log(`getting ${key}!`);
    return Reflect.get(target, key, receiver);
  },
  set: function (target, key, value, receiver) {
    console.log(`setting ${key}!`);
    return Reflect.set(target, key, value, receiver);
  }
});
obj.count = 1
//  setting count!
obj.count
//  getting count!
//  setting count!
//  2

//target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为 var proxy = new Proxy(target, handler);

1
2
//target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为
var proxy = new Proxy(target, handler);

我们这里继续写一个简单的demo:

let person = { constructor: function(name, age = 20) { this.name = name; this.age = age }, addAge: function() { this.age ; }, getAge: function() { return this.age; } } var proxy = new Proxy(person, { get: function(target, property) { console.log(arguments); return target[property]; }, set: function(target, property) { console.log(arguments); } }); person.constructor('叶小钗', 30); console.log(person.age) console.log(proxy.age)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
let person = {
    constructor: function(name, age = 20) {
        this.name = name;
        this.age = age
    },
    addAge: function() {
        this.age ;
    },
    getAge: function() {
        return this.age;
    }
}
 
var proxy = new Proxy(person, {
    get: function(target, property) {
        console.log(arguments);
        return target[property];
    },
    set: function(target, property) {
        console.log(arguments);
    }
});
 
person.constructor('叶小钗', 30);
console.log(person.age)
console.log(proxy.age)

图片 6

但是暂时我没有发现比较好的业务场景,比如说,我现在重写了一个实例的get方法,便能在一个全局容器中记录这个被执行了多少次,这里一个业务场景是:我一次个页面连续发出了很多次请求,但是我单页应用做页面跳转时候,我需要将所有的请求句柄移除,这个似乎也不是代理完成的工作,于是要使用ES6写代码,似乎可以暂时忽略代理。

console.log("出错行号:", lineNumber);

//ES6

结语

有了以上知识,基本从程序层面可以使用ES6写代码了,但是工程层面还需要引入webpack等工具,这些我们下次介绍吧。

1 赞 收藏 评论

图片 7

console.log("出错列号:", columnNumber);

var str = `aaaaaaaaaaaaaaaaaaa
            bbbbbbbbbbbbbbbbbb
            cccccccccccccccccc`;

console.log("错误详情:", errorObj);

//              Number Four : Destructuring Assignment
               //读取对象属性或者是数组元素

}

//ES5:

var eventUtils = {//跨浏览器事件

var a = {
    p1: "this is p1",
    p2: "this is p2"
};
 var p1 = a.p1;
 var p2 = a.p2;

getEvent: function (event) {//获取事件

//ES6

return event ? event : window.event

var {p1 , p2} = a;

},

var [p1,p2] = arr.split('n');

addHandler: function (ele, type, handler) {//事件监听

            //Number Five : Enhanced Object Literals
            //对象的强化

if (ele.addEventListener) {

//ES5

ele.addEventListener(type, handler)

var serviceBase = {port: 3000, url: 'azat.co'},
    getAccounts = function(){return [1,2,3]}

} else if (ele.attachEvent) {

var accountServiceES5 = {
    port: serviceBase.port,
    url: serviceBase.url,
    getAccounts: getAccounts,
    toString: function() {
        return JSON.stringify(this.valueOf())
    },
    getUrl: function() {return "http://"   this.url   ':'   this.port},
    valueOf_1_2_3: getAccounts()
};

ele.attachEvent('on' type, handler)

var accountServiceES5ObjectCreate = Object.create(serviceBase)
var accountServiceES5ObjectCreate = {
    getAccounts: getAccounts,
    toString: function() {
        return JSON.stringify(this.valueOf())
    },
    getUrl: function() {return "http://"   this.url   ':'   this.port},
    valueOf_1_2_3: getAccounts()
};

} else {

//ES6

ele['on' type]

var serviceBase = {port: 3000, url: 'azat.co'},
    getAccounts = function(){return [1,2,3]}
var accountService = {
    __proto__: serviceBase,
    getAccounts,
    toString() {
        return JSON.stringify((super.valueOf()))
    },
    getUrl() {return "http://"   this.url   ':'   this.port},
    [ 'valueOf_'   getAccounts().join('_') ]: getAccounts()
};
console.log(accountService);

}

            //Number Six: Arrow Functions
            //  箭头方法

},

//ES5:

removeHandler: function (ele, type, handler) {//移除监听

var _this = this
$('.btn').click(function(event){
    _this.sendData()
});

if (ele.removeEventListener) {

var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']
var messages = ids.map(function (value) {
    return "ID is "   value // explicit return
});

ele.removeEventListener(type, handler)

//ES6

} else if (ele.attachEvent) {

$('.btn').click((event) =>{
    this.sendData()
});

ele.detachEvent('on' type, handler)

var ids = ['5632953c4e345e145fdf2df8','563295464e345e145fdf2df9']
var messages = ids.map(value => `ID is ${value}`) // implicit return

} else {

                            //Number Seven : Promises
//ES5

ele['on' type]

setTimeout(function(){
    console.log('Yay!')
}, 1000)

}

//ES6

},

var wait1000 =  new Promise(function(resolve, reject) {
    setTimeout(resolve, 1000)
}).then(function() {
        console.log('Yay!')
    })

getTarget: function (event) {//事件目标

//OR

if (event.target) {

var wait1000 =  new Promise((resolve, reject)=> {
    setTimeout(resolve, 1000)
}).then(()=> {
        console.log('Yay!')
    })

return event.target

//                       Block-Scoped Constructs Let and Const
//                          块级作用域的变量声明

} else {

//ES5:

return event.srcElement

function calculateTotalAmount (vip) {
    var amount = 0
   if (vip) {
        var amount = 1
    }
    { // more crazy blocks!
       var amount = 100
        {
            var amount = 1000
        }
    }
    return amount
}

}

console.log(calculateTotalAmount(true));

},

//ES6

preventDefault: function (event) {//阻止默认事件

function calculateTotalAmount (vip) {
    var amount = 0 // probably should also be let, but you can mix var and let
   if (vip) {
        let amount = 1 // first amount is still 0
    }
    { // more crazy blocks!
       let amount = 100 // first amount is still 0
        {
            let amount = 1000 // first amount is still 0
        }
    }
    return amount
}

if (event.preventDefault) {

console.log(calculateTotalAmount(true));

return event.preventDefault

//let 使声明变量不会被提升
//let 严格限制了所声明变量的作用域,在哪声明在哪用
//let 不能重复声明同一个变量
//用 let 可以去掉函数的自执行

} else {

//                      Number Nine: Classes
//                           类

return event.returnValue = false

//New Concept in js:

}

class baseModel {
    constructor(options = {}, data = []) { // class constructor
       this.name = 'Base'
       this.url = ''
       this.data = data
        this.options = options
    }

},

    getName() { // class method
       console.log(`Class name: ${this.name}`)
    }
}

stopPropagation: function (event) {//阻止冒泡

//                            Number  Ten:  Modules
//                                   模块

if (event.stopPropagation) {

//ES5 : Node.js

return event.stopPropagation

module.exports = {
    port: 3000,
    getAccounts: function() {
        //***
    }
}

} else {

var service = require('module.js')
console.log(service.port) // 3000

return event.cancelBubble = true

//ES6

}

export var port = 3000
export function getAccounts(url) {
//...
}

}

import {port, getAccounts} from 'module'
console.log(port) // 3000

}

//OR

/*

import * as service from 'module'
console.log(service.port) // 3000

*通用ajax请求

*需引入jq库支持

*/

var xhr = {

ajaxRequest(options = {

type: 'Get'

}) {//同步ajax

var ajax = {

type: options.type,

url: options.url,

data: options.data,

dataType: 'json',

xhrFields: {

withCredentials: true

},

crossDomain: true

};

ajax.success = (result) => {

console.log(result)

};

$.ajax(ajax)

},

async asyncRequest(options = {

type: 'Get'

}) {//异步ajax

return new promise((resolve, reject) => {

var ajax = {

type: options.type,

url: options.url,

data: options.data,

dataType: 'json',

async: true,

xhrFields: {

withCredentials: true

},

crossDomain: true

};

ajax.success = (result) => {

resolve(result);

console.log(result)

};

ajax.error = (error) => {

resolve(error)

};

$.ajax(ajax)

})

}

}

/**

* @param {httpGet()}老版本http请求

* @method => httpGet({'请求url','传输data','回调函数'})

*/

function httpGet(services, data, callback) {

var url = 'example';

$.ajax({

url: url,

data: data,

dataType: 'json',

xhrFields: {

withCredentials: true

},

crossDomain: true,

success: function (data) {

var info = data['data']['info'];//返回数据格式视情况而定

if (data['ret'] == 200 && data['data']['code'] == 0) {

callback(info);

} else {

if (data['data']['code'] == 700) {

return;

}

var msg = data['data'] && data['data']['msg'] ? data['data']['msg'] : '';

msg = msg == '' && data['msg'] ? data['msg'] : msg;

//xhr.showmsg(msg);

}

},

error: function (data) {

}

})

}

/* 封装ajax函数

1 * @param 简易原生ajax

2 * @param {string}opt.type http连接的方式,包括POST和GET两种方式

3 * @param {string}opt.url 发送请求的url

4 * @param {boolean}opt.async 是否为异步请求,true为异步的,false为同步的

5 * @param {object}opt.data 发送的参数,格式为对象类型

6 * @param {function}opt.success ajax发送并接收成功调用的回调函数

7 */

function Ajax(opt) {

opt = opt || {};

opt.method = opt.method.toUpperCase() || 'POST';

opt.url = opt.url || '';

opt.async = opt.async || true;

opt.data = opt.data || null;

opt.success = opt.success || function () { };

var xmlHttp = null;

if (XMLHttpRequest) {

xmlHttp = new XMLHttpRequest();

}

else {

xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');

};

var params = [];

for (var key in opt.data) {

params.push(key '=' opt.data[key]);

}

var postData = params.join('&');

if (opt.method.toUpperCase() === 'POST') {

xmlHttp.open(opt.method, opt.url, opt.async);

xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=utf-8');

xmlHttp.send(postData);

}

else if (opt.method.toUpperCase() === 'GET') {

xmlHttp.open(opt.method, opt.url '?'

  • postData, opt.async);

xmlHttp.send(null);

}

xmlHttp.onreadystatechange = function () {

if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {

opt.success(xmlHttp.responseText);

}

};

}

/**

* 分页加载器

* @type {Function}

* 方法可扩展

*/

function pagingLoad(options) { //分页加载

if (!document.getElementById('load_txt')) {

this.loadTxt

document.createElement('div');

loadTxt.id = "load_txt";

loadTxt.style.textAlign = "center";

document.body.appendChild(loadTxt);

};

this.oPageLoad = {

page: 1,

el: options.el, //滚动的对象

apiUrl: options.url,

data: options.data || {},

tailload: true,

sucload: true,

totalpage: options.totalpage, //总页数

containArea: options.containArea, //内容区

callback: options.callback

};

var _this = this;

this.oPageLoad.el.onscroll = function () {

var scrollTop = this.scrollTop, //滚动条距顶部的高度

containHei = _this.oPageLoad.containArea.scrollHeight, //内容高度(scrollHeight)

clientHei = this.clientHeight; //可视高度

console.log('当前总页数'

  • _this.oPageLoad.totalpage, scrollTop, containHei, clientHei);

    if (_this.oPageLoad.page == _this.oPageLoad.totalpage && containHei - scrollTop - clientHei < 20) { //判断页码是否等于总页码且滚动条到达最底部

    if (_this.oPageLoad.tailload) {

_this.loadTxt.innerHTML = "已全部加载完成";

_this.oPageLoad.tailload = !_this.oPageLoad.tailload;

return;

} else {

_this.loadTxt.innerHTML = "已全部加载完成";

return;

}

};

if (containHei - scrollTop

  • clientHei < 20 && _this.oPageLoad.sucload) {

_this.oPageLoad.page ;

_this.oPageLoad.sucload = !_this.oPageLoad.sucload;

_this.loadTxt.innerHTML = "加载中...";

console.log('loading...第' _this.oPageLoad.page

  • '页');

_this.oPageLoad.data["page"] = _this.oPageLoad.page;

httpGet(_this.oPageLoad.apiUrl, _this.oPageLoad.data, function (data) {//请求加载

commonArray = commonArray.concat(data);

if (pagingLoadOption.containArea

document.getElementById('successList')) {//区分区块分区加载

var $successData = template('success_list', {info: commonArray,timeFormat: timeFormat });

$("#successList").html($successData);

} else {

var $inviteData = template('invite_list', {info: commonArray,timeFormat: timeFormat });

$("#inviteList").html($inviteData);

};

_this.loadTxt.innerHTML = "";

_this.oPageLoad.sucload = !_this.oPageLoad.sucload;

});

};

};

}

/**

* @param {function} 实用函数

* @method => bVersion()判断浏览器内核信息EXP:if(bVersion.iwx)

* @method => getExplore获取浏览器类型和版本,EXP:return Safari:9.0

* @method => toArray(['1','2'],2)仿Array.shift()方法从头部清除数组指定长度并返回新数组

* @method => initRun() 根据设备视口clientWidth宽度调节字体大小(基于750px宽度设计稿设置跟元素字体大小20px==1rem)

* @method => getQueryString() 获取url链接中参数对应的值

* @method => setStore(key, value) 本地存储key的value

* @method => getStore(key, exp, name) 取存储的数据:key[名称]exp[过期时间]name[指定命名的变量]

* @method => hasClass(ele,cls)判断element节点是否存在clasName('cls')

* @method => addClass(ele,cls)在hasClass判断基础上添加clasName('cls')

* @method => removeClass(ele,cls)在hasClass判断基础上移除clasName('cls')

* @method => getCookie(name)获取名为name的cookie值cookName[0]为键名,cookName[1]为键值

* @method => setCookie(name,value,days)设置过期时间戳expires为days名为name值为value的cookie

* @method => removeCookie(name)重新设置过期的cookie即可移除

* @method => randomColor生成随机颜色#xxxxxx

* @method => randomNum生成指定范围的随机数(min-max)

* @method => isPhoneNum(str)是否为手机号

*/

var utils = {

bVersion: function () {

var u = navigator.userAgent;

return { //移动终端浏览器内核信息

trident: u.indexOf('Trident') > -1, //IE内核

presto: u.indexOf('Presto') > -1, //opera内核

webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核

gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐内核

mobile: !!u.match(/AppleWebKit.*Mobile.*/) || !!u.match(/AppleWebKit/), //是否为移动终端

ios: !!u.match(/(i[^;] ;( U;)? CPU. Mac OS X/), //ios终端

android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或者uc浏览器

iPhone: u.indexOf('iPhone') > -1 || u.indexOf('Mac') > -1, //是否为iPhone或者QQHD浏览器

iPad: u.indexOf('iPad') > -1, //是否iPad

iwx: /MicroMessenger/i.test(u),//是否微信

iWeiBo: /Weibo/i.test(navigator.userAgent)//微博客户端

};

}(),

getExplore: function () {//获取浏览器类型和版本

var sys = {},

ua = navigator.userAgent.toLowerCase(),

s; (s = ua.match(/rv:([d.] )) like gecko/)) ? sys.ie = s[1] : (s = ua.match(/msie ([d.] )/)) ? sys.ie = s[1] : (s = ua.match(/edge/([d.] )/)) ? sys.edge = s[1] : (s = ua.match(/firefox/([d.] )/)) ? sys.firefox = s[1] : (s = ua.match(/(?:opera|opr).([d.] )/)) ? sys.opera = s[1] : (s = ua.match(/chrome/([d.] )/)) ? sys.chrome = s[1] : (s = ua.match(/version/([d.] ).*safari/)) ? sys.safari = s[1] : 0;

// 根据关系进行判断

if (sys.ie) return ('IE: ' sys.ie)

if (sys.edge) return ('EDGE: ' sys.edge)

if (sys.firefox) return ('Firefox: ' sys.firefox)

if (sys.chrome) return ('Chrome: ' sys.chrome)

if (sys.opera) return ('Opera: ' sys.opera)

if (sys.safari) return ('Safari: ' sys.safari)

return 'Unkonwn'

},

toArray(arr, len) {

len = len || 0;

var i = arr.length

  • len;

    var ret = new Array(i);

    while (i--) {

ret[i] = arr[i len];

}

console.log(ret);

return ret

},

hasClass: function (ele, cls) {//true||false

return (new RegExp('(\s|^)'

  • cls '(\s|$)')).test(ele.className);

},

addClass: function (cls) {

if (!hasClass(ele, cls)) {

ele.className = '' cls;

}

},

removeClass: function (cls) {

if (hasClass(ele, cls)) {

var exp = new RegExp('(\s|^)'

  • cls '(\s|$)');

ele.className = ele.className.replace(exp, ' ');

}

},

getCookie: function (name) {

var cookArr = document.cookie.replace(/s/g, "").split(';');

for (var i = 0, len = cookArr.length; i < len; i ) {

var cookName = cookArr[i].split('=');

if (cookName[0] == name) {

return decodeURIComponent(cookName[1]);

}

};

return '';

},

setCookie: function (name, value, days) {

var date = new Date();

date.setDate(date.getDate()

  • days);

    document.cookie = name '=' value ';expires='

  • date;

},

removeCookie: function (name) {

//设置过期cookie会自动移除

setCookie(name, '1', -1)

},

randomColor: function () {

return '#' ('00000' (Math.random() * 0x1000000 << 0).toString(16)).slice(- 6);

},

rendomNum: function (min, max) {

return Math.floor(Math.random() * (max - min) min);

},

isPhoneNum: function (str) {

return /^(0|86|17951)?(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$/.test(str)

},

copy: function (event) {//有选择性使用

var input = document.createElement('input');

input.type = "text";

input.value = "contain to copy";

event.currentTarget.appendChild(input);

input.select();

document.execCommand('copy', false, null);

},

initRun: function () {//响应式字体大小

var _this = this,

resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';

_this.fontAdapt();

window.onresize = function () {

_this.fontAdapt();

}

},

fontAdapt: function () {//div-width(375px)=>(html(20px)=>1rem)==(html(80px)=>html((80/2)px)=2rem)

var w = document.documentElement.clientWidth,

fz = w * 20 / 375;//375为基准视图宽度,为设计稿宽度/2; 20为自定义根字体像素大小

document.getElementsByTagName(html)[0].style.fontSize = fz 'px';

},

getQueryString: function (key) { //正则获取url后面的参数值'?service=&name=name'=>name

const reg = new RegExp("(^|&)"

  • key "=([^&]*)(&|$)");

    const result = window.location.search.substr(1).match(reg);

    return result ? decodeURIComponent(result[2]) : null;

},

setStore(key, value) { //localStorage存储数据 key[名称]value[数据]=>(配合store.min.js使用)

const storeTime = new Date().getTime();

value['setKeyTime'] = storeTime;

store.set(key, value);

},

getStore(key, exp, name) { //取存储的数据:key[名称]exp[过期时间]name[指定命名的变量]

const getKeyData = store.get(key);

exp && getKeyData && (new Date().getTime()

  • getKeyData.setKeyTime > exp) && store.remove(key) && (name && (name = store.get(key)));

    return getKeyData;

},

showmsg(msg) {//提示框

const $formMsg = document.getElementById('form-msg');

if ($formMsg == null || $formMsg == "") {

const tipEle = document.createElement("div");

tipEle.className = "tc form-msg";

tipEle.id = "form-msg";

tipEle.innerHTML = msg;

document.body.appendChild(tipEle);

} else {

$formMsg.style.display = "block";

$formMsg.innerHTML = msg;

}

setTimeout(() => {

document.getElementById('form-msg').style.display = "none";

}, 1000);

}

}

utils.initRun();

/**

* localStorage兼容性处理

*/

if (!window.localStorage) {

Object.defineProperty(window, "localStorage", new (function () {

var aKeys = [], oStorage = {};

Object.defineProperty(oStorage, "getItem", {

value: function (sKey) { return sKey ? this[sKey] : null; },

writable: false,

configurable: false,

enumerable: false

});

Object.defineProperty(oStorage, "key", {

value: function (nKeyId) { return aKeys[nKeyId]; },

writable: false,

configurable: false,

enumerable: false

});

Object.defineProperty(oStorage, "setItem", {

value: function (sKey, sValue) {

if (!sKey) { return; }

document.cookie = escape(sKey) "="

  • escape(sValue) "; path=/";

},

writable: false,

configurable: false,

enumerable: false

});

Object.defineProperty(oStorage, "length", {

get: function () { return aKeys.length; },

configurable: false,

enumerable: false

});

Object.defineProperty(oStorage, "removeItem", {

value: function (sKey) {

if (!sKey) { return; }

var sExpDate = new Date();

sExpDate.setDate(sExpDate.getDate()

  • 1);

    document.cookie = escape(sKey) "=; expires=" sExpDate.toGMTString()

  • "; path=/";

},

writable: false,

configurable: false,

enumerable: false

});

this.get = function () {

var iThisIndx;

for (var sKey in oStorage) {

iThisIndx = aKeys.indexOf(sKey);

if (iThisIndx === -1) { oStorage.setItem(sKey, oStorage[sKey]); }

else { aKeys.splice(iThisIndx, 1); }

delete oStorage[sKey];

}

for (aKeys; aKeys.length > 0; aKeys.splice(0, 1)) { oStorage.removeItem(aKeys[0]); }

for (var iCouple, iKey,

iCouplId = 0, aCouples

document.cookie.split(/s*;s*/); iCouplId < aCouples.length; iCouplId ) {

iCouple = aCouples[iCouplId].split(/s*=s*/);

if (iCouple.length > 1) {

oStorage[iKey = unescape(iCouple[0])] = unescape(iCouple[1]);

aKeys.push(iKey);

}

}

return oStorage;

};

this.configurable = false;

this.enumerable = true;

})());

} else {

return window.localStorage

}

/**

* 原生js仿jq常用API操作DOM

* @type {Object}

* @method $(".selector").method()

* @method {.css}=>$(".selector").css({Obj})

* @return this

*/

//$ selector

function $(selector) {

return document.querySelector(selector)

}

//hide()

Object.prototype.hide = function () {

this.style.display = "none";

return this;

};

//show()

Object.prototype.show = function () {

this.style.display = "block";

return this;

};

//hasClass()

Object.prototype.hasClass = function (cName) {

return !!this.className.match(new RegExp("(\s|^)"

  • cName "(\s|$)"));

}

//addClass()

Object.prototype.addClass = function (cName) {

if (!this.hasClass(cName)) {

this.className = " " cName;

}

return this;

}

//removeClass()

Object.prototype.removeClass = function (cName) {

if (this.hasClass(cName)) {

this.className = this.className.replace(new RegExp("(\s|^)"

  • cName "(\s|$)"), " ");

}

return this;

}

//parent()

Object.prototype.parent = function () {

return this.parentNode;

}

//next()

Object.prototype.next = function () {

return this.nextElementSibling;

}

//prev()

Object.prototype.prev = function () {

return this.previousElementSibling;

}

//siblings()

Object.prototype.siblings = function () {

var chid = this.parentNode.children;

var eleMatch = [];

for (var i = 0, l = chid.length; i < l; i ) {

if (chid[i] != this) {

eleMatch.push(chid[i]);

}

}

return eleMatch;

}

//css()

Object.prototype.css = function (cssObj) {

var cssStr = '';

function objToCssStr(cssObj) {

for (var k in cssObj) {

cssStr = k ':' cssObj[k] ';'

};

return cssStr

};

this.style.cssText = objToCssStr(cssObj);

}

/**

* @desc 判断原生类型

* @return {Boolean}

*/

function isObject(obj) {//Object or not

return Object.prototype.toString.call(obj) === '[object Object]'

}

function isNumber(num) {//Number or not

return Object.prototype.toString.call(num) === '[object Number]'

}

function isString(str) {//String or not

return Object.prototype.toString.call(str) === '[object String]'

}

function isArray(arr) {//Array or not

return Object.prototype.toString.call(arr) === '[object Array]'

}

function isBoolean(boolean) {//Boolean or not

return Object.prototype.toString.call(boolean) === '[object Boolean]'

}

function isFunction(fn) {//Function or not

return Object.prototype.toString.call(fn) === '[object Function]'

}

function isRegExp(reg) {//RegExp or not

return Object.prototype.toString.call(reg) === '[object RegExp]'

}

function looseEqual(a, b) {//check two parameter is looslyEqual or not(===)

if (a === b) { return true }

var isObjectA = isObject(a);

var isObjectB = isObject(b);

if (isObjectA && isObjectB) {

try {

var isArrayA = Array.isArray(a);

var isArrayB = Array.isArray(b);

if (isArrayA && isArrayB) {

return a.length === b.length && a.every(function (e, i) {

return looseEqual(e, b[i])

})

} else if (!isArrayA && !isArrayB) {

var keysA = Object.keys(a);

var keysB = Object.keys(b);

return keysA.length === keysB.length && keysA.every(function (key) {

return looseEqual(a[key], b[key])

})

} else {

/* istanbul ignore next */

return false

}

} catch (e) {

/* istanbul ignore next */

return false

}

} else if (!isObjectA && !isObjectB) {

return String(a) === String(b)

} else {

return false

}

};

本文由pc28.am发布于前端技术,转载请注明出处:ES6的十二个新特色,本身征集的做事js库

上一篇:品质的法门 下一篇:没有了
猜你喜欢
热门排行
精彩图文
  • 品质的法门
    品质的法门
    9 种改革 AngularJS 品质的艺术 2017/07/20 · JavaScript· AngularJS 初藳出处: JustinSpencer   译文出处:oschina    AngularJS 是当下利用非常遍布的 web app应用框架,随
  • 高质量滚动,实例解析防抖动和节流阀
    高质量滚动,实例解析防抖动和节流阀
    实例解析防抖动和节流阀 2016/04/26 · JavaScript· DOM 本文由 伯乐在线 -涂鸦码龙翻译。未经许可,幸免转发! 立陶宛共和国(Republic of Lithuania卡塔尔语出处:
  • 安插最棒执行,营造打包优化_javascript技术_脚本
    安插最棒执行,营造打包优化_javascript技术_脚本
    Webpack 4 配置最佳实践 2018/06/22 · JavaScript· webpack 原文出处:Zindex    Webpack 4 发布已经有一段时间了。Webpack 的版本号已经来到了4.12.x。但因为 Webpack官方还
  • 前端安全
    前端安全
    Web 安全之 XSS 2018/05/25 · JavaScript· 1 评论 ·XSS 原文出处:今日头条技术博客    1.CSRF 2.XSS 基本概念 攻击原理 防御措施 什么是XSS 跨站脚本攻击(Cross Site
  • 说说Float那个被埋没的志向,重新认识Box
    说说Float那个被埋没的志向,重新认识Box
    什么是BFC 2016/01/09 · CSS · 2评论 ·BFC 原文出处:大搜车前端团队博客    这是我10个月前写的一篇关于BFC的文章,因为接下来要写一篇关于FFC的文章了,然