JavaScript进阶

一 面向对象

1 ES6以前的对象

1 基本对象的建立

1 定义一个函数(构造器)对象,使用this定义属性
2 使用new 和构造器建立一个新对象
当使用new关键字后,其函数的调用将再也不是函数,而是一个原型,就以这个原型为模板,构造出本身的实例,而后进行对应的个性化操做,将其当作构造器来处理其特殊的属性或方法。前端


//古老的定义对象的方式 
var  obj= {
    a:'abc',
    b:'123',
    c:'[1,2,3,4]',
}
console.log(obj.a,obj.b,obj.c) 
function fn(x){
    this.x=x;
}
console.log(typeof(fn)) // 此处返回是一个函数
function  fn1(x,y) {
    this.x=x;
    this.y=y;
    console.log(this)  //指代函数自己,而不是实例化后的结果
    console.log(arguments)
}
a=new  fn1(10,20)  //对象构建,fn1由普通函数变成了一个构造器,new 先作对象,基于原型将a进行处理,经过对象亏帮属性
console.log(a.x,a.y)

结果以下 node

JavaScript进阶

2 继承关系

function  fn(x,y) {
    console.log('fn')
    this.x=x; //初始化属性 
    this.y=y;
    this.show=()=> ('show')  //初始化方法,及函数 
}
//继承
function  fn1(x,y,z) {
    console.log('fn1')
    fn.call(this,x,y);  //调用父类构造器,
    this.z=z;
}

a=new  fn1(1,2,3)
console.log('fn1',a)  //此处将a修改为一个对象,及字典,其对象中包含着全部的属性和方法
console.log(a.show(),a.x,a.y,a.z)

结果以下 react

JavaScript进阶

2 ES6之中的对象

1 要求和基本定义处理

1 类的定义使用class 关键字,建立的本质仍是函数,是一个特殊的函数
2 一个类只能拥有一个名为constructor的构造方法,若是没有显示的定义一个构造方法,则会默认添加一个constructor方法
3 继承使用extends 关键字
4 一个构造器可使用super关键字来调用父类的构造函数
5 类没有私有属性webpack

class  fn{   //定义类
    constructor(x,y){ 
        console.log('fn')
        this.x=x;  //定义属性 
        this.y=y;
    }
    show ()  //定义方法 
    {  
        console.log(this,this.x,this.y)
    }
}
//继承关系 
class  fn1 extends  fn{   //使用extends表示继承 
    constructor(x,y,z){
        console.log('fn1')
        super(x,y);  //调用父类方法,必须传入对应的值,不然父类无入值则会报错。
        this.z=z;
    }
}
a=new  fn1(1,2,3)
console.log(a.show())  //调用父类的方法
console.log(a.x,a.y,a.z)

结果以下 web

JavaScript进阶

2 函数重载

函数重载及函数名称相同,参数个数或类型不一样,此处称为重载
子类汇总直接能够重写父类的方法,若是须要使用父类的方法,则使用super.method()的方式调用npm

class  fn{   //定义类
    constructor(x,y){ 
        console.log('fn')
        this.x=x;  //定义属性 
        this.y=y;
    }
    show ()  //定义方法 
    {  
        console.log(this,this.x,this.y)
    }
}

class  fn1 extends  fn{   //使用extends表示继承 
    constructor(x,y,z){
        console.log('fn1')
        super(x,y);  //调用父类方法,必须传入对应的值,不然父类无入值则会报错。
        this.z=z;
    }
    show(){  //属性重载操做
        console.log(this,this.x,this.y,this.z)
    }
}
a=new  fn1(1,2,3)
console.log(a.show())  //重载后的属性调用
console.log(a.x,a.y,a.z)

结果以下编程

JavaScript进阶

使用箭头函数重写方法json

class  fn{   //定义类
    constructor(x,y){ 
        console.log('fn')
        this.x=x;  //定义属性 
        this.y=y;
    }
    show = () => console.log(this,this.x,this.y)
}

class  fn1 extends  fn{   //使用extends表示继承 
    constructor(x,y,z){
        console.log('fn1')
        super(x,y);  //调用父类方法,必须传入对应的值,不然父类无入值则会报错。
        this.z=z;
    }
    show  = ()  => console.log(this,this.x,this.y,this.z)
}
a=new  fn1(1,2,3)
console.log(a.show())  //重载后的属性调用
console.log(a.x,a.y,a.z)

3 类和属性的继承前后次序

class  fn{   //定义类
    constructor(x,y){ 
        this.x=x;  //定义属性 
        this.y=y;
        this.show=() => console.log('this fn',this.x,this.y)
    }
    show = () => console.log('fn',this.x,this.y)
}

class  fn1 extends  fn{   //使用extends表示继承 
    constructor(x,y,z){
        super(x,y);  //调用父类方法,必须传入对应的值,不然父类无入值则会报错。
        this.z=z;
        this.show=()  => console.log('this fn1',this.x,this.y,this.z);
    }
    show  = ()  => console.log('fn1',this.x,this.y,this.z);
}
a=new  fn1(1,2,3)
console.log(a.show())

结果以下 数组

JavaScript进阶

此处默认调用的是子类的属性,浏览器

class  fn{   //定义类
    constructor(x,y){ 
        this.x=x;  //定义属性 
        this.y=y;
        this.show=() => console.log('this fn',this.x,this.y)
    }
    show = () => console.log('fn',this.x,this.y)
}

class  fn1 extends  fn{   //使用extends表示继承 
    constructor(x,y,z){
        super(x,y);  //调用父类方法,必须传入对应的值,不然父类无入值则会报错。
        this.z=z;
        // this.show=()  => console.log('this fn1',this.x,this.y,this.z);
    }
    show  = ()  => console.log('fn1',this.x,this.y,this.z);
}
a=new  fn1(1,2,3)
console.log(a.show())

结果以下

JavaScript进阶

此处调用的是子类的方法

class  fn{   //定义类
    constructor(x,y){ 
        this.x=x;  //定义属性 
        this.y=y;
        this.show=() => console.log('this fn',this.x,this.y)
    }
    show = () => console.log('fn',this.x,this.y)
}

class  fn1 extends  fn{   //使用extends表示继承 
    constructor(x,y,z){
        super(x,y);  //调用父类方法,必须传入对应的值,不然父类无入值则会报错。
        this.z=z;
        // this.show=()  => console.log('this fn1',this.x,this.y,this.z);
    }
    // show  = ()  => console.log('fn1',this.x,this.y,this.z);
}
a=new  fn1(1,2,3)
console.log(a.show())

结果以下

JavaScript进阶

class  fn{   //定义类
    constructor(x,y){ 
        this.x=x;  //定义属性 
        this.y=y;
        // this.show=() => console.log('this fn',this.x,this.y)
    }
    show = () => console.log('fn',this.x,this.y)
}

class  fn1 extends  fn{   //使用extends表示继承 
    constructor(x,y,z){
        super(x,y);  //调用父类方法,必须传入对应的值,不然父类无入值则会报错。
        this.z=z;
        // this.show=()  => console.log('this fn1',this.x,this.y,this.z);
    }
    // show  = ()  => console.log('fn1',this.x,this.y,this.z);
}
a=new  fn1(1,2,3)
console.log(a.show())

结果以下

JavaScript进阶

总结
属性和方法定义,不论是父类仍是子类。都是优先使用属性,若两个都是方法,则子类覆盖父类 ,若是都是属性,则是子类覆盖父类,子类的优先级是高于父类的

4 静态方法

静态属性目前支持不彻底
在方法前面加上static就是静态方法了,此处的静态方法是在类中进行调用的,而不是在实例中。

class  fn{   //定义类
    constructor(x,y){ 
        this.x=x;  //定义属性 
        this.y=y;
    }
    static  show = () => console.log('fn',this.x,this.y)
}
console.log(fn.show())
a=new fn(1,2)
console.log(a.show())

结果以下

JavaScript进阶

3 this 中坑

1 问题引出

虽然JavaScript和C和Java都有this,但JavaScript的表现是不一样的
缘由在于C,Java是静态编译语言,this是在编译期间绑定的,而js是动态语言,是在运行期间锁定的。

var  school= {  //此处定义一个对象,其中包含name和getNamefunc两个,其中name是属性,getNamefunc是方法,其返回值是一个函数
name: 'test',
getNamefunc: function(){
    console.log(this.name)
    console.log(this)
    console.log('-----------------')
    return  function() {
        console.log(this == global);  //检查其是不是全局的
        return this.name;
    }
    }
}

method=school.getNamefunc //此属性调用后返回的是函数的类型,并未调用外层函数
a=method()  //调用外层函数
a()  //调用内层函数

结果以下

JavaScript进阶

上面的返回结果是其this本应该是school,却被处理称为了全局函数

var  school= {  //此处定义一个对象,其中包含name和getNamefunc两个,其中name是属性,getNamefunc是方法,其返回值是一个函数
name: 'test',
getNamefunc: function(){
    console.log(this.name)
    console.log(this)
    console.log('-----------------')
    return  function() {
        console.log(this == global);  //检查其是不是全局的
        return this.name;
    }
    }
}

method=school.getNamefunc() //此处调用外层函数
a=method()  //调用外层函数

结果以下

JavaScript进阶

此处的结果是this仍然是全局属性


分析上例
第三行的打印结果是true,则代表当前是global的做用于,由于调用这个返回的函数是直接调用的,这是一个普通函数调用,所以this是全局对象

第四行undefined,就是由于this是global,因此没name属性

这就是函数调用的时候,调用方式不一样,this对应的对象不一样,它已经不是C++,Java的指向实例自己了。

this的问题,这是历史遗留问题,新版本只能兼容了。

2 解决办法

1 显式传参

var  school= {  //此处定义一个对象,其中包含name和getNamefunc两个,其中name是属性,getNamefunc是方法,其返回值是一个函数
name: 'test',
getNamefunc: function(){
    console.log(this.name)
    console.log(this)
    console.log('-----------------')
    return  function(that) {  //经过此处传递参数的方式改变
        console.log(that == global);  //检查其是不是全局的
        return that.name;
    }
    }
}

console.log(school.getNamefunc()(school))

结果以下

JavaScript进阶

2 ES3 引入了apply和 call方法

经过call将指定的this进行指定了。JavaScript中指代的是这个,其余的Java指定的不一样,普通函数的调用和对象的调用是不一样的,普通函数的调用中的thi指代的是全局变量,而在对象中调用,默认传递的值是this的自己

var  school= {  //此处定义一个对象,其中包含name和getNamefunc两个,其中name是属性,getNamefunc是方法,其返回值是一个函数
    name: 'test',
    getNamefunc: function(){
        console.log(this.name)
        console.log(this)
        console.log('-----------------')
        return  function() {
            console.log(this == global);  //检查其是不是全局的
            return this.name;
        }
        }
    }

    var school1={
        'name': 'test1'
    }
    method=school.getNamefunc() //此属性调用后返回的是函数的类型,并未调用外层函数
    console.log(method.call(school1))  //经过call将其this传递进去,
    console.log('---------------')
    console.log(method.call(school))
    console.log('++++++++++++++++')
    console.log(method.apply(school)) //经过apply,将其this传递过去

结果以下

JavaScript进阶

相关源码

JavaScript进阶

apply和 call方法都是函数对象的方法
apply传递其余参数使用数组,call传递其余参数须要使用可变参数收集。相关状况以下

var  school= {  //此处定义一个对象,其中包含name和getNamefunc两个,其中name是属性,getNamefunc是方法,其返回值是一个函数
    name: 'test',
    getNamefunc: function(){
        console.log(this.name)
        console.log(this)
        console.log('-----------------')
        return  function(x,y,z) {
            console.log(this == global,x,y,z);  //检查其是不是全局的
            return this.name;
        }
        }
    }

    method=school.getNamefunc() //此属性调用后返回的是函数的类型,并未调用外层函数
    console.log('---------------')
    console.log(method.call(school,[1,2,3])) //此处传地过去不会解构,是一个参数
    console.log('++++++++++++++++')
    console.log(method.apply(school,[1,2,3])) //经过apply,会解构,

结果以下

JavaScript进阶

3 ES5中引入了bind方法

var  school= {  //此处定义一个对象,其中包含name和getNamefunc两个,其中name是属性,getNamefunc是方法,其返回值是一个函数
    name: 'test',
    getNamefunc: function(){
        console.log(this.name)
        console.log(this)
        console.log('-----------------')
        return  function(x,y,z) {
            console.log(this == global,x,y,z);  //检查其是不是全局的
            return this.name;
        }
        }
    }

method=school.getNamefunc() //此属性调用后返回的是函数的类型,并未调用外层函数
console.log(method.bind(school)(1,2,3))

结果以下

JavaScript进阶

bind 是会返回一个新函数,其和偏函数类似

4 ES6中支持了this箭头函数

var  school= {  //此处定义一个对象,其中包含name和getNamefunc两个,其中name是属性,getNamefunc是方法,其返回值是一个函数
    name: 'test',
    getNamefunc: function(){
        console.log(this.name)
        console.log(this)
        console.log('-----------------')
        return  (x,y,z)  => {
            console.log(this == global,x,y,z);  //检查其是不是全局的
            return this.name;
        }
        }
    }

school1={
    name:'test1'
}
method=school.getNamefunc() //此属性调用后返回的是函数的类型,并未调用外层函数
console.log(method(1,2,3))

结果以下

JavaScript进阶

最外层使用箭头函数的结果

var  school= {  //此处定义一个对象,其中包含name和getNamefunc两个,其中name是属性,getNamefunc是方法,其返回值是一个函数
    name: 'test',
    getNamefunc: () => {
        console.log(this.name)
        console.log(this)
        console.log('-----------------')
        return  (x,y,z)  => {
            console.log(this == global,x,y,z);  //检查其是不是全局的
            return this.name;
        }
        }
    }

school1={
    name:'test1'
}
method=school.getNamefunc() //此属性调用后返回的是函数的类型,并未调用外层函数
console.log(method(1,2,3))

结果以下

JavaScript进阶

所以,通常不建议最外层使用箭头函数

4 高阶对象

1 简介

Mixin 模式,及混合模式,这是一种不用继承就能复用的技术,主要仍是为了解决多重继承的问题,多重继承路径是个问题

JS是基于对象的,类和对象都是对象模板

混合Mixin,指的是将一个对象的所有或者部分拷贝到另外一个对象上去了,其实就是属性,能够将多个类或者对象混合成一个类或者对象,任何一个对象均可以做为另外一个对象的原型。

2 基础代码

class test{
    constructor(){
        console.log('test',this)
        if (typeof(this.show) !=='function')  {
            throw  new  ReferenceError('should define stringify.');
        }
    }
}
class test1  extends  test{
    constructor(x,y){
        super();
        this.x=x;
        this.y=y;
    }
    show(){
        return   `test1 ${this.x} ${this.y}`;
    }
}
p=new  test1(1,2)
console.log(p.show())

结果以下

JavaScript进阶

此处的核心是谁调用的问题,上述父类的this是子类的实例,而不是子类调用父类后父类造成的实例,所以这也是验证经过的缘由。

class test{
    constructor(){
        console.log('test',this)
        if (typeof(this.show) !=='function')  {
            throw  new  ReferenceError('should define stringify.');
        }
    }
}
class test1  extends  test{
    constructor(x,y){
        super();
        this.x=x;
        this.y=y;
    }
    show(){
        return   `test1 ${this.x} ${this.y}`;
    }
}

class test2  extends  test1 {
    constructor(x,y,z)  {
        super(x,y);
        this.z=z;
    }
}
p=new  test2(1,2)
console.log(p.show())  //此处本身自己没有show,则经过调用父类的show来实现,上述传入的this 仍然是子类的实例,

结果以下

JavaScript进阶

3 高阶对象实现

经过在test中使用函数并传递参数的方式将test1的相关属性注入进去,相关代码以下

初步改造结果以下

class test1{
    constructor(x,y){
        this.x=x;
        this.y=y;
    }
    show(){
        return   `test1 ${this.x} ${this.y}`;
    }
}
const  test = function  test(SUP)   {  //此函数的返回值是一个类,经过将类test1传入其中进行相关的操做处理并进行输出
    return   class    extends  SUP {
          constructor(...args) {
              super(...args);
              console.log('test',this)
              if (typeof(this.show) !=='function')  {
                  throw  new  ReferenceError('should define stringify.');
          }
      }
    }
}

class test2 extends  test(test1){
  constructor(x,y,z)  {
      super(x,y);
      this.z=z;
  }
}
p=new test2(1,2,3)
console.log(p.show())

结果以下

JavaScript进阶

将上述函数修改成箭头函数结果以下

class test1{
    constructor(x,y){
        this.x=x;
        this.y=y;
    }
    show(){
        return   `test1 ${this.x} ${this.y}`;
    }
}
const  test =  SUP=>  class    extends  SUP {
          constructor(...args) {
              super(...args);
              console.log('test',this)
              if (typeof(this.show) !=='function')  {
                  throw  new  ReferenceError('should define stringify.');
          }
      }
    }

class test2 extends  test(test1){
  constructor(x,y,z)  {
      super(x,y);
      this.z=z;
  }
}
p=new test2(1,2,3)
console.log(p.show())

注意:
test(test1)这一步其实是一个匿名箭头函数的调用,返回一个新的类型,test2继承自这个新的类型,加强了功能,react大量使用了这种Mixin技术。

二 异常

1 基础实例

try {
    throw  1; // 抛出异常
} catch (error){    //此处不用指定异常类型,此处的error是上面的throw扔出来的
    console.log(error,typeof(error));
}

JavaScript进阶

抛出一个对象

try {
    throw  {}; // 抛出异常
} catch (error){    //此处不用指定异常类型,此处的error是上面的throw扔出来的
    console.log(error,typeof(error));
}

结果以下

JavaScript进阶

抛出一个函数

try {
    throw  () => console.log(2); // 抛出异常
} catch (error){    //此处不用指定异常类型,此处的error是上面的throw扔出来的
    console.log(error,typeof(error));
}

结果以下

JavaScript进阶

2 抛出异常

try {
    throw  Error('new Error'); // 抛出异常
} catch (error){    //此处不用指定异常类型,此处的error是上面的throw扔出来的
    console.log(error,typeof(error));
}

结果以下

JavaScript进阶

try {
        throw ReferenceError('new Error')
    } catch  (error){  //此处不用指定类型  ,此处的error是接上面扔出来的东西
        console.log(error,typeof(error));
    };

结果以下

JavaScript进阶

try {
        throw ReferenceError('new Error')
    } catch  (error){  //此处不用指定类型  ,此处的error是接上面扔出来的东西
        console.log(error,typeof(error));  //此处不影响下面的执行
        console.log(error.constructor);  //此处的执行结果是函数
    };

结果以下

JavaScript进阶

try {
        throw ReferenceError('new Error')
    } catch  (error){  //此处不用指定类型  ,此处的error是接上面扔出来的东西
        console.log(error,typeof(error));  //此处不影响下面的执行
        console.log(error.constructor.name);  //获取函数名称
    };

结果以下

JavaScript进阶

3 必须执行的finally

try {
        throw null;
    } catch  (error){  //此处不用指定类型  ,此处的error是接上面扔出来的东西
        console.log(error,typeof(error));
        console.log(error.constructor.name); //一切皆函数
    } finally  {  //定义必须执行的函数
        console.log('1325345234')
    }

结果以下

JavaScript进阶

三 解构和相关方法

1 JS数组解构

1 常量的修改

常量的声明和初始化时不能被分开的,常量只是对象的地址不能发生改变了,并非其中的内容也不能改变了。

const   l1=[1,2,3,4]
l1.pop() //l1虽然是一个常量,但其能够被修改
console.log(l1)

JavaScript进阶

2 参数解构

彻底解构

const   l1=[1,2,3,4]
const  [a,b,c,d]=l1 
console.log(a,b,c,d)

JavaScript进阶

丢弃解构

const   l1=[1,2,3,4]
const  [a,b,,c,d]=l1 
console.log(a,b,c,d)

结果以下

JavaScript进阶

const   l1=[1,2,3,4]
const [a]=l1
console.log(a)

结果以下

JavaScript进阶

可变变量

const   l1=[1,2,3,4]
const  [a,...d]=l1 
console.log(a,d)

结果以下

JavaScript进阶

const   l1=[1,2,3,4]
const  [a,...d,e]=l1  //可变长必须放置在最后面 
console.log(a,d,e)

JavaScript进阶

默认值

const   l1=[1,2,3,4]
const [x=10,,,,y=20]=l1  //能覆盖的覆盖,不能覆盖的保持原值,先赋值,再覆盖,
console.log(x,y)

JavaScript进阶

3 复杂数组解构

const arr = [1,[2,3],4];  //三个元素,嵌套解构
const [a,[b,c],d]=arr;  
console.log(a,b,c,d);  //直接拆开 
const [e,f]=arr;  // 只有两
console.log(e,f);  // 第一个和第二个 

const [g,h,i,j=18]=arr;  // 三个 加1 ,则是对应的
console.log(g,h,i,j);
const  [k,...l]=arr;  // 此处会将后面两个元素进行搬家
console.log(k,l);

结果以下

JavaScript进阶

2 数组方法

1 方法描述

方法 描述
push(...items) 尾部追多个元素
pop() 移除最后一个元素,并返回它
map 引入处理函数来处理数组中的每个元素,返回新的数组
filter 引入处理函数处理数组中的每个元素,此处理函数返回true的元素保留,不然该元素被过滤掉,保留的元素构成新的数组返回
foreach 迭代全部元素,无返回值

2 push方法

const   l1=[1,2,3,4]
l1.push([5,6,7,8])
l1.push(...['a','b','c'])
l1.push(9,10,11)
console.log(l1)

结果以下

JavaScript进阶

3 pop 方法

const   l1=[1,2,3,4]
l1.push([5,6,7,8])
l1.push(...['a','b','c'])
l1.push(9,10,11)
console.log(l1.pop())
console.log(l1.pop())
console.log(l1.pop())
console.log(l1)

结果以下

JavaScript进阶

4 map方法

const  abs = (x) => x**2
const   l1=[1,2,3,4]
console.log(l1.map(abs))

结果以下

JavaScript进阶

5 filter

const  abs  = function  (x)  {
    if (x%2==0) {
        return  true;
    }
    else {
        return  false;
    }
}
const   l1=[1,2,3,4]
console.log(l1.filter(abs))

结果以下

JavaScript进阶

6 foreach

const   l1=[1,2,3,4]
const  newarr= l1.forEach(x=>x+10) //无返回值
console.log(newarr,l1)

结果以下

JavaScript进阶

7 数组练习

有一个数组const arr=[1,2,3,4,5];,要求计算出全部元素平方值是偶数且大于10的。

代码一

const   arr=[1,2,3,4,5];
console.log(arr.filter(x => ((x**2)%2==0 && (x**2)>10)))

代码二,若平方是偶数,则该数也应该是偶数,则以下

const   arr=[1,2,3,4,5];
console.log(arr.filter((x=> x%2==0 && x**2>10)))

代码三,经过map来实现

const   arr=[1,2,3,4,5];
console.log(Math.log2(((arr.filter(x=>x%2==0)).map(x=>x**2)).filter(x=>x>10)))

代码四,求10的平方根,而后再进行相关比较

const   arr=[1,2,3,4,5];
const  cond=10
const  cond1=Math.sqrt(cond)
console.log(arr.filter(x=>x%2==0 && x> cond1))

3 对象解构

var  metadata= {
        title: "Seratchpad",
        translations :[
            {
            locale: "de",
            localization_tags: [],
            last_edit: "2019-01-01T08:11:11",
            url: "/de/docs/Tools/scratchpad",
            title: "JavaScript-Umgebung"
            }
        ],
        url: "/en-US/docs/Tools/Scratchpad" 
}
var  {title:enTitle,translations:[{title: localeTitle}] }=metadata; //: 后面的是重命名

console.log(enTitle)
console.log(localeTitle)

JavaScript进阶

4 对象操做

1 基本介绍

object 的静态方法 描述
object.keys(obj) ES5开始支持,返回全部key
object.values(obj) 返回全部值,实验阶段,支持较差
object.entries(obj) 返回全部值,试验阶段,支持较差
object.assign(target,...sources) 使用多个source对象,来填充target对象,返回target对象
var  obj = {
        a:100,
        b:200,
        c:()=>{}
    }
console.log(Object.keys(obj)) //返回全部的键
console.log(Object.values(obj)) //返回全部的值
console.log(Object.entries(obj))//返回全部的键和值
obj1={
    d:300,
    e:400,
}
let  obj2=Object.assign(obj,obj1)  //返回新的对象
console.log()

结果以下

JavaScript进阶

四 模块化

1 简介

ES6 以前,JS没有出现模块化系统
JS主要是在前端浏览器中使用,JS文件下载缓存到客户端,在浏览器中执行。
好比简单的表达本地验证,漂浮一个广告。


服务器端使用ASP,JSP等动态网页技术,将动态生成数据嵌入一个HTNL模板,里面夹杂着JS后使用<script>标签,返回浏览器端。
这时候的JS知识一些简单的函数和语句组合。


2005年后,随着Google大量使用了AJAX技术后,能够一步请求服务器端数据,带来了前端交互的巨大变化,前端的功能需求愈来愈多,代码也愈来愈多,随着JS文件的增长,灾难性的后果产生了,因为习惯了随便写,JS脚本中各类全局变量污染,函数名冲突,没法表达脚本之间的依赖关系。此时便有待模块化的产生。


2008年V8引擎发布后,2009年诞生了nodejs,支持服务端JS编程,但没有模块化是不能够的,以后产生了commonjs规范。

commonjs 规范
使用全局require函数来导入模块,模块名就是文件名,使用exports导出变量
exports包含了全部须要导出的函数

require会将exports中的全部函数遍历出来便可进行相关的处理操做。


AMD规范
AMD (asynchronous module definition)异步模块定义,使用异步方式加载模块,模块的加载不影响它后面语句的执行,全部依这个模块的语句,都须要定义在一个回调函数中,回调函数中使用模块的变量和函数,等模块加载完成以后,这回调函数才执行,就能够安全的使用模块中的资源了。其实现就是AMD/requireJS.AMD虽然是异步,可是会预先加载和执行。


CMD(Common Module Defintion),使用seajs,做者是淘宝前端玉伯,兼容并解决了requirejs的问题,CMD推崇as lazy as possible,尽量的懒加载。

2 ES6模块中的导入

import语句,导入另外一个模块导出的绑定

export语句,从模块中导出函数,对象,值等,供其余模块import导入


建立两个文件

1.js和2.js

1.js中写入以下数据

//导出默认类
export  default   class A {//此处设置默认导出,能够导出类,函数,变量和常量
        constructor(x){
            this.x=x;
        }
        show() {
            console.log(this.x)
        }    
}
//导出函数 
export var foo =() =>console.log('foo function')

//导出变量 
export  const CONST='aaa';

2.js中进行相关导入

以下

import {foo,CONST}  from  './1'; //此处若不指定./当前目录。则默认是全局变量
import A from "./1";

let a=new A(10);
a.show();

foo();
console.log(CONST)

因为相关的引擎均不支持import 和export操做,所以须要经过相关的附加模块来实现此种操做
上述中使用{}能够同时导入多个环境变量。

3 转译(label)

1 简介

转译就是从一种语言代码到另外一个语言代码,固然可使从高版本转译到低版本的支持语句。
因为JS存在不一样的版本,不一样浏览器的兼容问题可经过transpiler转译工具进行解决,而babel就是其中的一种,官网以下
https://www.babeljs.cn

2 本地安装label

1 须要生成package.json文件,用于编译使用,可经过npm init 进行初始化

JavaScript进阶

生成文件以下

JavaScript进阶

3 设置国内镜像,用于下载相关依赖包速度更快

.npmrc文件,此文件可经过touch .npmrc建立
能够放置到npm目录下的npmrc文件中。也能够放置到用户家目录中,也能够放置到项目根目录中,此处放置到项目根目录,以下

registry=http://registry.npm.taobao.org

以下
JavaScript进阶

4 安装

npm install  babel-core babel-cli  --save-dev

JavaScript进阶

相关参数说明

--save-dev 说明
当你为你的模块安装一个依赖模块时,正常状况下你得先安装他们(在模块根目录下npm install mode-name),而后连同版本号手动将其添加到模块配置文件package.json中的依赖中


--save 和--save-dev能够省略你手动修改package.json文件的步骤。
npm install mode-name --save 自动将模块和版本号添加到dependencies部分,用于在打包至线上的依赖关系时使用
npm install mode-name --save-dev 自动将模块和版本号添加到devdependencise部分

查看package.json中的内容

JavaScript进阶

5 准备目录

项目根目录中建立src和lib目录
src是源码目录;
lib是目标目录;

JavaScript进阶

6 配置 babel

在目录根目录下建立.babelrc文件,json格式,其babelrc是和babel运行相关的
内容以下

{
    "presets":["env"]
}

JavaScript进阶

7 修改配置文件package.json,肯定转换源和目标

{
  "name": "test",
  "version": "1.0.0",
  "description": "from test",
  "main": "1.js",
  "scripts": {
    "build": "babel src -d  lib"
  },
  "author": "test",
  "license": "MIT",
  "devDependencies": {
    "babel-cli": "^6.26.0",
    "babel-core": "^6.26.3"
  }
}

此处是scripts中的修改,其若目标为目录,则为-d,若目标为文件,则为-o。

8 准备源文件

将1.js 和 2.js放置到src下

JavaScript进阶

9 安装依赖

npm install  babel-preset-env --save-dev

JavaScript进阶

10项目根目录执行npm run build

npm run  build

JavaScript进阶
JavaScript进阶

转换后的结果

JavaScript进阶

JavaScript进阶

运行以下

JavaScript进阶

后期的经过webpack来实现全部的的联动,自动化的打包操做所有进行处理。

相关文章
相关标签/搜索