JavaScript笔记(2):JavaScript的基本知识

AJAX

AJAX的全称是Asynchronous JavaScript and XML,就是异步响应网络的请求,从字面意思上看,AJAX是异步执行的,AJAX需要借助于XMLHttpRequest对象
发送AJAX请求时,域名必须和当前页面完全一致,即

1、协议相同(http和https不同)
2、端口相同

AJAX请求外域有下面几种方法:
1、使用Flash插件发送HTTP请求,这种方法可以绕过浏览器的安全限制,但必须安装Flash
2、在同源域名下架设一个代理服务器来转发,JavaScript负责把请求进行转发到代理服务器:

'/proxy?url=http://www.sina.com.cn'

3、使用JSONP,但是这个方式只能用GET请求

HTML

JavaScript
function refreshPrice(data) {
    var p = document.getElementById('test-jsonp');
    p.innerHTML = '当前价格:' +
        data['0000001'].name +': ' + 
        data['0000001'].price + ';' +
        data['1399001'].name + ': ' +
        data['1399001'].price;
}

function getPrice() {
    var
        js = document.createElement('script'),
        head = document.getElementsByTagName('head')[0];
    js.src = 'http://api.money.126.net/data/feed/0000001,1399001?callback=refreshPrice';
    head.appendChild(js);
}

4、CORS:最新的浏览器全面支持HTML5,在引用外语资源时,除了JavaScript和CSS外,都要验证CORS,它的过程是这样的,当JavaScript向外域发出请求,浏览器收到响应后,首先检查Access-Control-Allow-Origin是否包含本域,如果包含,则请求成功,反之,请求失败,就是说,决定权在服务器端

Promise

Promise是一种对程序的异步处理结果进行处理的对象,由浏览器直接支持
Promise的作用是这样的,它把执行代码和对代码执行结果处理进行了分离,看下面一个例子

HTML
    JavaScript
    //初始化log
    function initLogging(){
        var logging = document.getElementById('test-promise-log');
        while(logging.children.length > 1){
            logging.removeChild(logging.children[logging.children.length - 1]);
        }
    }
    
    //添加log
    function log(s){
        var logging = document.getElementById('test-promise-log');
        var p = document.createElement('p');
        p.innerHTML = s;
        logging.appendChild(p);
    }
    
    //执行Promise的测试
    function PromiseTest1(){
        initLogging();//首先进行初始化操作
        new Promise(function(resolve,reject){
            log('start new Promise...');
            var timeOut = Math.random() * 2;
            log('set timeout to:' + timeOut + ' seconds.');
            setTimeout(function(){
            if(timeOut < 1){
                log('call resolve()...');
                resolve('200 OK');
            }else{
                log('call reject()...');
                reject('timeout in ' + timeOut + ' seconds.');
            }
        },timeOut * 1000);
        }).then(function(r){
            log('Done:' + r);
        }).catch(function(reason){
            log('Failed:' + reason);
        });
    }
    

    上面的代码是一个异步执行的方式,结构大概是这样

    new Promise(
        function(resolve,reject){
        if(条件满足){
          resolve('result');
        }else{
          reject('reson');
        }
    }).then(function).catch(function);
    

    假如条件满足,执行resolve,被then捕获,假如条件不满足,执行reject,被catch捕获

    Promise的常用形式如下面所示,它的执行是这样的,先执行job1,假如执行的结果满足条件,则执行job2,依次下去直到最后一个任务,假如在执行的过程中,有一个不满足,则被捕获

    job1.then(job2).then(job3).catch(handleError);
    

    看下面一个例子

    HTML(同上)
    JavaScript
    //执行乘法
    function multiply(input){
        return new Promise(function(resolve,reject){
            log('calculating ' + input + ' x ' + input + '...');
            setTimeout(resolve,500,input * input);
        });
    }
    
    //执行加法
    function add(input){
        return new Promise(function(resolve,reject){
            log('calculating ' + input + ' + ' + input + '...');
            if(input < 10000)
                setTimeout(resolve,500,input + input);
            else
                setTimeout(reject,500,input);
        });
    }
    
    function PromiseTest2(){
        var p = new Promise(function(resolve,reject){
            log('start new Promise...');
            resolve(123);
        });
    
        p.then(multiply)
         .then(add)
         .then(multiply)
         .then(add)
         .then(function(result){
            log('Got value:' + result);
         }).catch(function(r){
            log('Number is too big:' + r);
         });
    }
    

    Promise.all([p1,p2]).then();//这个方法是让数组中的两个Promise对象都进行返回之后,然后再执行then中的方法,代码如下

    function PromiseTest3(){
        var p1 = new Promise(function(resolve,reject){
            setTimeout(resolve,Math.random() * 100,'P1');
        });
    
        var p2 = new Promise(function(resolve,reject){
            setTimeout(resolve,Math.random() * 100,'P2');
        });
    
        Promise.all([p1,p2]).then(function(results){
            alert(results);
        });
    }
    

    Promise.race([p1...pn]).then();//这个则是对数组中的Promise对象进行执行,then的执行条件是其中最先执行完的一个Promise对象,代码同上,把all改为race即可

    Canvas

    是HTML5新增的组件,像是一块幕布,可以使用JavaScript在其中绘制各种图表、动画等
    1、首先我们需要创建一个canvas节点
    2、我们使用获取getElemeById的方式来获取这个画布
    3、使用canvas.getContext('2d');//来获取这个画布的句柄,接着就能操作这个画布了
    如下

    绘制一个图形
    HTML
    
    
    
    
    JavaScript
    //画一个笑脸
    function CanvaPaintSmileFace(){
        var canvas = document.getElementById('test-canvas');
        var ctx = canvas.getContext('2d');
        ctx.clearRect(0,0,200,200);
        ctx.fillStyle = '#dddddd';
        ctx.fillRect(10,10,130,130);
    
        var path = new Path2D();
        path.arc(75,75,50,0,Math.PI*2,true);
        path.moveTo(110,75);
        path.arc(75,75,35,0,Math.PI,false);
        path.moveTo(65,65);
        path.arc(60,65,5,0,Math.PI*2,true);
        path.moveTo(95,65);
        path.arc(90,65,5,0,Math.PI*2,true);
        ctx.strokeStyle = '#0000ff';
        ctx.stroke(path);
    }
    
    绘制一个文本
    HTML(同上)
    JavaScript
    //文本绘制
    function CanvasTest2(){
        var canvas = document.getElementById('test-canvas-1'),
            ctx = canvas.getContext('2d');
    
        ctx.clearRect(0,0,canvas.width,canvas.height);
        ctx.shadowOffsetX = 2;
        ctx.shadowOffsetY = 2;
        ctx.shadowBlur = 2;
        ctx.shadowColor = '#666666';
        ctx.font = '24px Arial';
        ctx.fillStyle = '#333333';
        ctx.fillText('Something Just Happens',20,40);
    }
    

    JQuery

    作用

    1、消除浏览器差异,不需要写冗长的代码来针对不同的浏览器进行优化
    2、简洁的操作DOM的方法
    3、轻松实现动画、修改CSS等各种操作
    jQuery的使用只要在head下面添加下面这句就可以了

    
    
    $符号

    $是jQuery的别名,本质上是一个函数

    选择器

    $('#dom-id');//按照id进行查找,返回的是一个数组,而不是undefined或者null,所以不用进行判断

    var div = $('#domid');
    var divDom = div.get(0);//假设存在,获取第一个DOM元素
    var another = $(divDom);//将DOM包装为jQuery对象
    

    $('tag-name');//按照tag进行查找,返回的是一个数组

    var ps = $('p');
    ps.length;
    

    $('.class-name');//按照class进行查找

    var a = $('.red.green');
    

    $('[name=email]');//按照属性进行查找
    $('[name^=icon]');//找出所有以icon开头的属性
    $('[name$=with]');//找出所有以with结尾的属性
    $('[class^=icon-]');//找出所有以icon-开头的class属性
    $('p.red,div.green');//找出所有tag为p且class为red和tag为div和class为green的属性
    $('input[name=email]');//找出所有input中name为email的属性
    看一个实例

    HTML
    
    

    JavaScript

    Haskell

    Erlang

    Python

    注册新用户

    JavaScript
    //jQuery的选择器
    function jQueryHandle(){
        var type = -1;
        var num = $('#get-val');
        type = Number(num.val());//默认将字符串转化为数字
        var selected = null;
        switch(type){
            case 1://仅选择JavaScript
                selected = $('#para-1');
                break;
            case 2://仅选择Erlang
                selected = $('.color-red.color-green');
                break;
            case 3://选择JavaScript和Erlang
                selected = $('.color-red');
                break;
            case 4://选择所有编程语言
                selected = $('[class^=color-]');
                break;
            case 5://选择名字
                selected = $('input[name=name]');
                break;
            case 6://选择邮件和名字
                selected = $('input[name=email],input[name=name]');
                break;
            default:
                return alert('无效操作');
        }
        if(!(selected instanceof jQuery)){
            return alert('不是有效的jQuery对象')
        }
        $('#test-jquery').find('*').css('background-color','');
        selected.css('background-color', '#ff0051');
    }
    
    层级选择器

    层级之间可以用空格隔开,如下

    $('ul.lang li.lang-javascript');//选择class为lang下的class为lang-javascript的所有属性,不同层级之间可以用逗号隔开
    
    子选择器

    子选择器类似于层级选择器,但是限定了层级关系必须是父子关系

    $('ul.lang>li.lang-javascript');//选出了ul中class为lang中的子class为lang-javascript的属性
    
    过滤器

    过滤器一般不单独使用,而是附加在选择器上,如下

    $('ul.lang li');//选择class为lang下的所有li
    $('ul.lang li:first-child');//选择class为lang下的第一个li
    $('ul.lang li:last-child');//选择class为lang下的最后一个li
    $('ul.lang li:nth-child(even)');//选择class为lang下的所有奇数li
    $('ul.lang li:nth-child(2)');//选择class为lang下的第2个li
    
    表单相关
    :input;//可以选择,
    */
    var
        input = $('#test-input'),
        select = $('#test-select'),
        textarea = $('#test-textarea');
    
    input.val(); // 'test'
    input.val('[email protected]'); // 文本框的内容已变为[email protected]
    
    select.val(); // 'BJ'
    select.val('SH'); // 选择框已变为Shanghai
    
    textarea.val(); // 'Hello'
    textarea.val('Hi'); // 文本区域已更新为'Hi'
    

    修改DOM结构

    html();//jQuery中的暴力方法,直接对节点进行设置
    append();//为节点新增一个子节点,可以添加DOM对象,jQuery对象,函数对象
    prepend();//把DOM元素放在最前面
    after();//把节点插入到指定位置之后
    before();//把节点插入到指定位置之前
    

    删除节点

    remove();//直接删除节点
    下面的一个例子是对节点进行添加再排序

    HTML
     
    • JavaScript
    • Python
    • Swift
    JavaScript
    //排序节点
    function SortNode(){
        var init = ['Pascal','Lua','Ruby'];
        var lis = $('#test-div>ul');
        lis.find('li').map(function(){
            init.push(this.innerText);
            this.remove();
        });
        output(init);
        init.sort();
        for(var i = 0;i < init.length;i++){
            var li = document.createElement('li');
            li.innerHTML = '' + init[i] + '';
            lis.append(li);
        }
    }
    

    事件

    我们把DOM节点和JavaScript的处理函数进行绑定,那么当我们对节点点击或者键盘输入时,我们就会触发JavaScript中对应的函数

    click me
    var a = $('#test-link');
    a.on('click',function(){
        alert('Hello!');
    });
    

    其中on方法用来对事件的绑定

    on();//绑定事件,可以指定事件的类型
    click();//直接绑定单击事件
    dblclick();//双击事件
    mouseenter();//鼠标进入事件
    mouseleave();//鼠标离开事件
    mousemove();//鼠标移动事件
    hover();//鼠标不管进入还是退出都触发事件
    
    keydown();//键盘按下事件
    keyup();//键盘松开事件
    keypress();//键盘按一次后触发
    
    focus();//DOM获取焦点时触发
    blur();//DOM失去焦点时触发
    change();//当input、select、textarea的内容修改时触发
    submit();//form提交时触发
    ready();//页面被载入并且DOM树完成初始化后触发,ready函数的关键就在于将节点的事件绑定到初始化的时候
    

    ready事件的写法

    $(function(){
        $('#testFom').submit(function(){
            alert('submit!');
        });
    });
    

    事件参数
    所有的时间都会传入Event对象作为参数,我们可以对这些对象进行操作

    $(function(){
        $('#testMouseMoveDiv').mousemove(function(c){
            $('#testMouseMoveSpan').text('pageX = ' + e.pageX + ',pageY = ' + e.pageY);
        });
    });
    

    取消绑定
    使用off('click',function)可以解除节点事件的绑定,如下

    function hello(){
        alert('Hello!');
    }
    
    a.click(hello);
    
    //10s之后解除绑定
    setTimeout(function(){
        a.off('click',hello);
    },10000);
    

    事件的触发条件
    change函数可以监控事件的触发

    var input = $('#test-input');
    input.change(function(){
        console.log('changed...');
    });
    
    input.val('change it!');//这个做法无法触发该事件
    input.change();//假如我们调用了JavaScript修改了值,如上面一行,那么我们在这里可以调用无参的change方法来进行调用
    

    浏览器的安全限制
    敏感操作将被浏览器拦截,看下面的例子

    var btn1 = $('#testbtn1');
    var btn2 = $('#testbtn2');
    
    function popupTestWindow(){
        window.open('/');
    }
    
    btn1.click(function(){
        popupTestWindow();
    });
    
    btn2.click(function(){
        //由于是延迟弹出,将被拦截
        setTimeout(popupTestWindow,100);
    });
    

    看下面一个例子

    HTML
    请选择想要学习的编程语言:

    反选

    JavaScript
    //实现事件处理的函数
    function LanguageHandle(){
        var 
            form = $('#test-form'),
            langs = form.find('[name=lang]'),
            selectAll = form.find('label.selectAll :checkbox'),
            selectAllLabel = form.find('label.selectAll span.selectAll'),
            deselectAllLabel = form.find('label.selectAll span.deselectAll'),
            invertSelect = form.find('a.invertSelect');
        //重置状态
        form.find('*').show().off();
        form.find(':checkbox').prop('checked', false).off();
        deselectAllLabel.hide();
        //拦截form提交事件
        form.off().submit(function(e){
            e.preventDefault();
            alert(form.serialize());
        });
    
        //对每一个语言都设置选项
        langs.click(function(event){
            var i = 0;
            var out = 0;
            for(i = 0;i < langs.length;i++){
                var check = langs.get(i).checked;
                if(check === false){
                    out++;
                }
            }
    
            if(out === 0){
                selectAll.prop('checked',true);
                selectAllLabel.text('全不选');
            }else{
                selectAll.prop('checked',false);
                selectAllLabel.text('全选');
            }
        });
    
        //设置全选和全不选
        selectAll.click(function(event) {
            var i = 0;
            var isselected = selectAll.is(':checked');
            for(i = 0;i < langs.length;i++){
                langs.get(i).checked = isselected;
            }
            if(isselected === true)
                selectAllLabel.text('全不选');
            else
                selectAllLabel.text('全选');
        }); 
    
        //设置反选
        invertSelect.click(function(event) {
            var i = 0;
            var out = 0;
            for(i = 0;i < langs.length;i++){
                var check = langs.get(i).checked;
                langs.get(i).checked = !check;
                if(check)
                    out++;
            }
            output(out);
            if(out === 0)
            {
                selectAll.prop('checked',true);
                selectAllLabel.text('全不选');
            }else{
                selectAll.prop('checked',false);
                selectAllLabel.text('全选');
            }
        });
    }
    

    动画
    show/hide
    直接以无参的调用会显示或隐藏DOM元素,添加参数进去,就变成了动画

    var div = $('#test-show-hide');
    div.hide(3000);//在3秒钟内渐变
    div.show('slow');//在0.6秒后慢慢显示
    div.toggle('slow');//根据当前状况显示或隐藏
    

    slideUp/slideDown/slideToggle
    在垂直方向逐渐展开或收缩

    fadeIn/fadeOut/fadeToggle
    以淡入或淡出的方式显示

    animate
    可以实现任意的动画效果,使用的方式如下

    var div = $('#test-animate');
    div.animate({
        //CSS样式
    },3000,function(){
        //动画完成后的操作
    });
    //上面的作用是在3s内达到样式表所描述的状态,完成之后调用function
    

    ajax
    jQuery在全局对象绑定了ajax(),所以可以处理AJAX请求。ajax(url,settings)是接收AJAx请求的方法,setting的设置有下面几个

    async:是否异步执行,默认为true,不要设置为false
    method:发送的方法,缺省为GET,也可指定为POST,PUT
    contentType:发送POST请求的格式
    date:发送的数据,可以是字符串、数组或Object
    headers:发送的额外的HTTP头
    dataType:接收的数据格式,可以指定为html,xml,json,text
    具体的使用
    var ajaxh = $.ajax('/api/categories',{
        dataType:'json'
    });
    

    get
    这个方法是针对ajax的GET方法的,写法如下

    var jqxhr = $.get('/path/to/resource',{
        name:'Bob Lee',
        check:1
    });
    

    post
    和get类似,但是第二个参数被序列化为application/x-www-form-urlencode

    var jqxhr = $.post('/path/to/resource',{
        name:'Bob Lee',
        check:1
    });
    

    getJSON
    通过get来获取json

    var jqxhr = $.getJSON('/path/to/resource', {
        name: 'Bob Lee',
        check: 1
    }).done(function (data) {
        // data已经被解析为JSON对象了
    });
    

    拓展
    编写jQuery插件

    错误处理
    try...catch...finally,使用的方法和Java一样,不再赘述
    错误捕获有3种方式

    try...catch...finally;//捕获且最终处理
    try...catch;//捕获
    try...finally;//没有捕获,都会处理
    

    throw new Error('错误信息'):异常的抛出

    错误传播
    假如一个程序内部发生了错误,但是它自身没有捕获,错误就会被抛到外层函数,直到被JavaScript引擎捕获,程序终止

    异步错误处理
    异步执行只是设置了一个响应或者延迟之后再进行操作,因此,我们不能在回调函数外捕获,而是只能在毁掉函数内捕获,如下

    try {
        $btn.click(function () {
        try{
            var
                x = parseFloat($('#x').val()),
                y = parseFloat($('#y').val()),
                r;
            if (isNaN(x) || isNaN(y)) {
                throw new Error('输入有误');
            }
            r = x + y;
            alert('计算结果:' + r);
        
        }catch(e){
          alert('输入错误1!');
        }
        });
    } catch (e) {
        alert('输入有误2!');
    }
    

    如上,我们只能捕获错误1,因为回调函数执行完就退出了,我们捕获的只是响应

    underscore
    当我们使用Array时,我们有map和filter方法来进行数组的操作,但是对象没有这些好用的方法,另外低版本的浏览器也没有这些方法,我们可以使用undercore来进行这样的操作,这个操作可以让object也可以进行这样的操作

    你可能感兴趣的:(JavaScript笔记(2):JavaScript的基本知识)