美文网首页
JavaScript 精粹

JavaScript 精粹

作者: 扶搏森 | 来源:发表于2017-11-01 00:40 被阅读0次

    数据类型

    JavaScript 是弱类型语言,但并不是没有类型,JavaScript可以识别下面7种不同类型的值:

    基本数据类型

    • Boolean
    • Number
    • String
    • null
    • undefined
    • Symbol (es6,引入唯一值)

    Oject

    • Array
    • RegExp
    • Date
    • Math

    可以使用 typeof 判断数据类型,操作符 返回一个字符串,但并非返回的所有结果都符合预期

    typeof false  //boolean
    typeof .2     //number
    typeof NaN    //number
    typeof ''       //string
    typeof undefined   //undefined
    typeof Symbol()    //symbol
    typeof new Date()   //object
    typeof []               //object
    typeof alert            //function
    typeof null       //object
    typeof not_defined_var.  //undefined
    

    变量

    在应用程序中,使用变量来为值命名。变量的名称称为identifiers

    声明

    • 使用关键字 var-> 函数作用域
    • 使用关键字 let-> 块作用域(block scope local variable)
    • 直接使用:全局作用域

    变量提升

    JavaScript中可以引用稍后声明的变量,而不会引发异常,这概念成为变量声明提升(hoisting)

    console.log(a);   //undefined
    var a=2;
    

    等同于

    var a;
    console.log(a);
    a=2;
    

    函数

    一个函数就是一个可以被外部代码调用 ( 或者函数本身递归调用 ) 的子程序

    定义函数

    • 函数声明
    • 函数表达式
    • Function 构造函数
    • 箭头函数
    function fn(){}
    var fn=functoin(){}
    var fn=new Function(arg1,arg2,...argN,funcBody);//和eval一样进入了javascript解释内核中,几乎不用
    var fn=(params)=>{}
    

    arguments

    • arguments:一个包含了还递给当前执行函数参数的类似于数组的对象
    • arguments.length:传给函数的参数的数目,实参
    function foo(){
        return arguments;
    }
    foo(1,2,3);  //Arguments[3]
    //{"0":1,"1":2,"2":3}
    

    rest

    对arguments的一种优化

    function foo(...args){
        return args;
    }
    foo(1,2,3);  //Array[3]
    //[1,2,3]
    function fn(a,b,...args){
        return args;
    }
    fn(1,2,3,4,5);
    //[3,4,5] 返回数组
    

    default

    function fn(a=2,b=3){
        return a+b;
    }
    fn(2,3);   //5
    fn(2);     //5
    fn();      //5
    

    对象

    JavaScript中对象是可变 键控集合 (keyed colletions)

    定义对象

    • 字面量
    • 构造函数
    var obj={
        prop:'value',
        fn:function(){}
    }
    var date=new Date();
    

    构造函数

    构造函数和普通函数并没有区别,使用new关键字调用就是构造函数,使用构造函数可以是实例化一个对象

    函数的返回值有两种可能

    • 显式调用 return 返回 return 后表达式的求值
    • 没有调用 return 返回 undefined
    function People(name,age){
        this.name=name;
        this.age=age;
    }
    var people=new People('Byron',26);
    

    构造函数的返回值

    • 没有返回值
    • 简单数据类型
    • 对象类型

    前两种情况构造函数返回构造对象的实例,实例化对象正是利用的这个特性

    第三种构造函数和普通函数表现一致,返回 return 后表达式的结果

    prototype

    • 每个函数都有一个 prototype的对象属性,对象内有一个constructor属性,默认指向函数本身
    • 每个对象都有一个 __proto__ 的属性,属性指向父类型的 prototype
    function Person(name){
        this.name=name;
    }
    Person.prototype.print=function(){
        console.log(this.name);
    }
    var p1=new Person('Jacket');
    console.log(p1);
    
    alt 构造函数内部情况

    this和作用域

    作用域可以通俗的理解

    • 我是谁
    • 我有哪些马仔

    其中我是谁的回答就是 this

    马仔就是我的局部变量

    this 场景

    普通函数

    • 严格模式:undefined
    • 非严格模式: 全剧对象

      1) Node:global
      1. 浏览器:window

    构造函数:对象的实例

    对象方法:对象本身

    call&apply

    • fn.call(context,arg1,arg2,...,argn)
    • fn.apply(context,args)

    通过其他函数调用这个方法产生一个函数作用域

    function isNumber(obj){
        //传入的实参去调用Object原型链上的toString方法,而不用自己本身的toString方法
        return Object.prototype.toString.call(obj)==='[object Number]';
    }
    

    Function.prototype.bind

    根据这个函数生成一个新的函数,这个新的函数作用域被我改掉了,老的是不变的

    bind 返回一个新函数,函数的作用域为 bind 参数

    function fn(){
        this.i=0;
        setInterval(function(){
            console.log(this.i++);
        }.bind(this),500);
    }
    fn();
    

    执行结果

    0
    1
    2
    3
    ...
    

    setInterval函数里面本来作用域this是undefined,通过绑定fn里面的this,将this传进去

    箭头函数

    箭头函数是ES6提供的新特性,是简写的函数表达式,拥有词法作用域和this

    function fn(){
        this.i=0;
        setInterval(()=>{
            //this指向外面的this
            console.log(this.i++);
        },500);
    }
    fn();
    

    执行结果和上面一样

    继承

    在JavaScript的场景,继承有2个目标,子类需要得到父类的:

    1.对象的属性(得到父类的属性)

    2.对象的方法(得到父类的方法)

    function inherits(child,parent){
        //创建一个parent.prototype的副本(浅拷贝)
        var _prototype=Object.create(parent.prototype);
        //_prototype的constructor.name指向的是parent的name,重新赋值child.constructor
        _prototype.constructor=child.prototype.constructor;
        child.prototype=_prototype;
    }
    function People(name,age){
        this.name=name;
        this.age=age;
    }
    People.prototype.getName=function(){
        return this.name;
    }
    //English继承People的方法,当English新增方法不改变父级的方法
    //English.prototype=People.prototype按址引用,English改变People也改变
    //寄生式组合继承
    function English(name,age,language){
        People.call(this,name,age);
        this.language=language;
    }
    inherits(English,People);
    

    ES6 class 与继承

    "use strict";
    class People{
        constructor(name,age){
            this.name=name;
            this.age=age;
        }
        getName(){
            return this.name;
        }
    }
    class English extends People{
        constructor(name,age,language){
            //调用父类构造函数,如果子类和父类构造函数相同,可不写constructor
            //如果写了constructor,没调super,就不能继承父类的方法了
            super(name,age);
            this.language=language;
        }
        introduce(){
            console.log('I am '+this.getName);
            console.log('I speak '+this.language);
        }
    }
    

    语法 label statement

    语句与表达式

    可以解释成语句的不会解释成表达式

    var x={a:1} //表达式 //{a:1}
    {a:1}     //语句   //{}里面的a是语句,1是表达式,输出1
    {a:1,b:2}   //逗号是表达式,b:2会报错
    

    立即执行函数

    //()里面必须是表达式,function(){}()要按照表达式来执行
    //function(){}为方法声明,function(){}()为方法调用
    (function(){}());
    (function(){})();
    [function(){}()];
    ~function(){}();
    !function(){}();
    +function(){}();
    -function(){}();
    delete function(){}();
    typeof function(){}();   //typeof是一种运算符
    void function(){}();
    new function(){}();
    var f=function(){}();
    1,function(){}();
    1^function(){}();
    1>function(){}();
    

    高阶函数

    高阶函数是把函数当作参数或者返回值是函数的函数

    回调函数

    [1,2,3,4].forEach(function(item){
        console.log(item);
    })
    

    闭包

    函数的嵌套,并且对外提供访问,产生闭包

    闭包由两部分组成

    • 函数
    • 环境:函数创建时作用域内的局部变量
    function makeCounter(init){
        var init=init||0;
        return function(){
            return ++init;
        }
    }
    var counter=makeCounter(10);
    console.log(makeCounter());
    console.log(makeCounter());
    

    典型错误

    for(var i=0;i<dom.length;i++){
        dom.eq(i).on('click',function(){
            console.log(i);
        })
    }
    
    for(var i=0;i<dom.length;i++){
        (function(i){
            dom.eq(i).on('click',function(){
                console.log(i);
            })
        })(i)
    }
    

    惰性函数

    function eventBinderGenerator(){
        if(window.addEventListener){
            return function(element,type,handler){
                element.addEventListener(type,handler,false);
            }
        }else{
            return function(element,type,handler){
                element.attachEvent('on'+type,handler.bind(element,window.event));
            }
        }
    }
    //第一次执行就把函数执行的结果保存下来,下次执行不会再去判断
    var addEvent=eventBinderGenerator();
    

    柯里化

    一种允许使用部分参数生成函数的方式

    function isType(type){
        return function(obj){
            return Object.prototype.toString.call(obj)==='[object '+ type ']';
        }
    }
    var isNumber=isType('Number');
    console.log(isNumber(1));
    console.log(isNumber('s'));
    
    function f(n){
        reuturn n*n;
    }
    function g(n){
        return n*2;
    }
    console.log(f(g(5)));
    function pipe(f,g){
        return f.call(null,g.apply(null,arguments));
    }
    var fn=pipe(f,g);
    console.log(fn(5));
    

    尾递归

    • 尾调用是指某个函数的最后一步是调用另一个函数
    • 函数调用自身,称为递归
    • 如果尾递归自身,就称为尾递归
      递归很容易发生 栈溢出 错误(stack overflow)

    反柯里化

    Function.prototype.uncurry=function(){
        return this.call.bind(this);
    }
    

    push 通用化

    var push=Array.prototype.push.uncurry();
    var arr=[];
    push(arr,1);
    push(arr,2);
    push(arr,3);
    console.log(arr);
    

    相关文章

      网友评论

          本文标题:JavaScript 精粹

          本文链接:https://www.haomeiwen.com/subject/sxfwpxtx.html