LingYanSi / blog

博客
https://github.com/LingYanSi/blog/issues
9 stars 0 forks source link

js相关 #6

Open LingYanSi opened 9 years ago

LingYanSi commented 9 years ago

js常用框架/库

etc

LingYanSi commented 9 years ago

1.Javascript的垃圾回收机制:

在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。 如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。

LingYanSi commented 9 years ago

2.闭包

在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。 --- 维基百科

其实这段引用已经说明了闭包的本质:引用了自由变量的函数,自由变量将和这个函数一同存在——这是理解闭包的关键。 这里有篇博客

LingYanSi commented 9 years ago

3.void

void有什么用呢,嗯,void会一直返回undefined,不论他的参数是什么

void(1)
void(function(){
return 1888
}())

这里有一篇介绍

LingYanSi commented 9 years ago

4.with

改变作用域链,但性能较低,不建议使用。

LingYanSi commented 9 years ago

5.如何使用canvas截图

先看下这个博空 html2canvas

LingYanSi commented 9 years ago

6.return

return跳出的当前程序所在的环境 比如说

        function bitch(){
            console.log('aaa');
            return ;
        }

        function eva(){
            bitch();
            console.log('bbb')
        }

        eva(); // --> aaa
                // --> bbb
LingYanSi commented 9 years ago

7.URL

URL中是search在前还是hash在前?

其中?search=a这种叫query,#hash叫fragment。

  • query的规定是以第一个?开始,至行尾或#结束。
  • fragment以#为开始,行尾为结束。 也就是说query必须在fragment之前。

另外根据query和fragment字符限定的规定,两者中都可以含有/和?,但不可以含有#。(还有其它的限制,这里是简要的说法,因为我们此处要讨论以?和#开头的字串)

LingYanSi commented 9 years ago

8.模板template

几次面试都被问到,知不知道前端模板,用没用过。 说到模板,我一直以为都是像jsp或者ejs那样的后端模板。 它们的原理也很是简单,请求接口【因为是请求本地,所以速度很快】,传入对象,然后插入数据。 但不是这样的,他们的意思是用在html里的模板。

前端模版

前端模版写在哪里呢?像angular他是直接卸载html里面,绑定数据的一种方式{{ bulalal }},但这样会有些问题,可能会导致用户看到花括号,体验不好。 一般的前端模版是卸载textarea或者script标签内,其中以写在script里居多 可以使用script标签的原因是

script的type属性默认是 text/javascript 如果是其他值,浏览器不会解析执行

说了这么多,为什么要用呢?

比如像art-template的使用

<script id="bitch" type="text/template">
        {{if bitch==false }}
            {{each list}}
                <div> {{$index}} : {{$value.username}}</div>
            {{/each}}
            <div>
                <p>{{party.name}}</p>
                <div>
                    {{each party.partner}}
                        {{if $value=="王羲之"}}
                            <p>{{$value}}</p>
                        {{/if}}
                    {{/each}}
                </div>
                <p>{{party.price}}</p>
            </div>
        {{/if}}
    </script>
    <script src="js/art-template.js"></script>
    <script>
        var util = {
            bitch: false,
            list:[
                {username:'李晓波'},
                {username:'李洪志'},
                {username:'张弛没'},
                {username:'宇文化及'}
            ],
            party:{
                name:'兰亭集',
                partner:[
                    '王羲之',
                    '顾炎武',
                    '路由',
                ],
                price:'黄金万两',
            }
        };
        var html = template('bitch',util);
        document.querySelector('#song').innerHTML = html ;
    </script>

他的主要功能在于表现层和数据层分离,并且模板封装了一些逻辑,不用再自己去拼接html 这么做用着还算不错。

先这样吧,去吃饭了

LingYanSi commented 8 years ago

PubSub

今天在给商品编辑添加功能时候,看到了PubSub这么个字符,是什么东西不太清楚 没有问菲哥,自己看了看,似乎是类似于【事件注册与派发】

function func(msg, data) {
    console.log(msg, data)
}
//事件注册
PubSub.subscribe('here.update', func);
//触发事件
PubSub.publish('here.update', {
    data: '数据过来咯'
});

有时间了,自己造一个 PubSubJS

它有什么用呢?

在React中,有的时候组建嵌套太深,或者不相干的组件,需要通信传递数据 使用PubSub就可以方便的解决问题

LingYanSi commented 8 years ago

lodash VS underscore

lodash 适用于现代浏览器 ie9及其以上,也有全兼容的版本 underscore 兼容全部

为什么要用他们呢?

因为【数组/字符串/函数/对象】等在不同浏览器上,所含有的属性、方法不同,比较新的特性老的浏览器上自然不支持 他们就像jquery磨平了浏览器的兼容性,可使用相关最新的es6特性,并且有所扩展。 但为什么不使用babel编译呢?只能所各有所长了

LingYanSi commented 8 years ago

验证用户登录

mgj,这边会在每次请求的时候,根据传递过来的cookie,来验证用户是否有权限进行相关操作。 cookie的读写由后端决定。这样做很爽。

LingYanSi commented 8 years ago

函数式、命令式

久闻函数式编程,今天再看阮一峰的博文时,看到一个很好的例子

var obj = {
    fun : function(){
        console.log('我是方法')
    }
};

obj.fun() ; // 这是函数式
delete obj.fun ; // 这是命令式
LingYanSi commented 8 years ago

时间循环 Event Loop 任务队列 Task Queue

Promise的队列与setTimeout的队列的有何关联? 在JS中只有一个时间循环,但可以有多个任务队列

两个概念 macrotask宏任务 microtask微任务

_macrotask_:script(整体代码)、setTimeout、setInterval、setImmediate _microtask_:promise(浏览器原生实现的)、process.nextTick(node)

浏览器执行时会 1.先从macrotask队列中取出第一个任务执行,执行完毕后从microtask队列中取出所有任务执行。 2.再从macrotask队列中取出第二个任务执行,再从microtask队列中取出所有任务执行。 如此这般。

LingYanSi commented 8 years ago

deep copy

突然想到一个捷径

var a = {name:'嘿嘿'};
var b = JSON.parse( JSON.stringify(a) );
LingYanSi commented 8 years ago

图片上传

直接上码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <style>
        #imageUploadIframe {
            display: none;
        }
    </style>
</head>

<body>
    <form action="upload.php" target="imageUploadIframe" method="post">
        <input type="file" accept="image/*" name="image">
    </form>
    <iframe name="imageUploadIframe" id="imageUploadIframe" style="display:none;"></iframe>

    <script>
        /*
         * 1. 传统的方式
         */
        // 提交表单,因为form 的 target="imageUploadIframe" 所以本页面不会刷新
        document.querySelector('[type="file"]').addEventListener('change', (event) => {
            event.value && document.querySelector('form').submit();
        })

        document.querySelector('#imageUploadIframe').addEventListener('load', function() {
            // iframe会在页面第一次加载时候,load一次,在form提交,后端返回输出后也会load
            // 后端输出地数据放在body里面
            var text = window.iframes[imageUploadIframe].document.body.contentText;
            // 解析数据
            var data = JSON.parse(text);
        });
        /*
         * 2. FormData
         */
        document.querySelect('input[type="file"]').addEventListener('change', function() {
            var form = document.querySelector('form');
            var xhr = new XMLHttpRequest();
            var formData = new FormData(form);
            xhr.open('POST', 'upload.php', true);
            xhr.send(formData);
        })
    </script>
</body>

</html>
LingYanSi commented 8 years ago

Error 错误类型

try{
    // 如果return了就不会执行catch
    return 1
    throw new Error('我是你爹')
}catch(e){
    console.log(e.message,e.name) // message错误信息 name错误类型
    return 2
}finally{
   // finally 会一直执行
   return 3
}
LingYanSi commented 8 years ago

jsonp


function jsonp(url,data,callback){
  // 参数校验
  // url必须,data非必需,callback非必需
  // data可以对象,也可以是function
  // 这层处理暂且不表

  return new function(){
   var script = document.createElement('script')
   // tag需要是唯一标识
   var tag = 'jsonp'+new Date().getTime()+ (Math.random()+'').replace('.','') 

   // 对象转字符串,暂时只考虑单级对象

   var str = ''
   for( var key in data){ 
      if(key=='callback') continue
      str += '&'+key+'='+ data[key]
   }
    script.src = url+'?callback='+tag + str
    document.head.appendChild(script)
    window[tag] = callback

    script.onload = function(){
      document.head.removeChild(script)
    }
}
}
LingYanSi commented 8 years ago

迭代器? jQuery delay的实现

        var iter = function(pipe){
                var obj = {
                    delay: function(time){
                        // 也应该加入到任务队列里面
                        obj.queueArr.push({type:0,arg:time})
                        obj.queueArr.length === 1 && this.next() 
                        return this
                    },
                    play: function(name){
                        // 加入到任务队列
                        obj.queueArr.push({type:1,arg:name})
                        obj.queueArr.length === 1 && this.next() 
                        return this
                    },
                    queueArr: [],
                    next: function(){
                        // 从任务队列中取任务
                        var job = obj.queueArr[0]
                        if(!job) return
                        // type = 1 立即执行
                        if( job.type==1 ){
                            // 从队列中移除任务
                            obj.queueArr.splice(0,1)

                            // 对参数进行处理
                            pipe(job.arg)

                            // 循环迭代
                            obj.next()
                        // type = 0 延时
                        }else{
                            var _this = this ;
                            setTimeout(function(){
                                console.log('延时了',job.arg)
                                obj.queueArr.splice(0,1)

                                obj.next()
                            },job.arg)
                        }
                    }
                }
                return obj
            }

使用

           new iter(function(arg){
                // 当type=1时,处理play里的参数
                var str = ''
                for(var key in arg){
                    str +=';'+key+':'+ arg[key]
                }
                $tran.style.cssText += str
            })
            .delay(2000)
            .play({width:'100px','background-color':'rgb(255, 0, 0)'})
            .delay(2000)
            .play({'height':'100px','transform':'translate3d(0,200px,0)'})
            .delay(1000)
            .play({'border-radius':'50%','background-color':'rgb(0, 255, 232)'})
LingYanSi commented 8 years ago

方法的私有状态

经常会遇到一种状况:发起一个ajax请求,要在请求结束之前,不可再次请求 之前的解决方案是:

app = {
    isAjaxing: false,
    fetch(){
    }
}

亦或是添加一个全局变量,这样做虽说功能可以实现,但不美观。 因为请求状态应该是属于fetch的私有状态,他不应该入侵到app上,或者其他地方

如下是一个更好的解决方案

var app = {
    fecth: (function(){
        let isAjaxing = false
        return function(){ 
            if(isAjaxing) {
                console.log('正在请求中,不可再次请求')
                return
            }
            isAjaxing= true
            setTimeout(()=>{
                console.log('请求结束')
                isAjaxing= false
            },3000)
        }
    })(),
}
LingYanSi commented 8 years ago

Cookie

使用koa setCookie死活不成功,几番查询,才知道是因为使用fetch的时候,credentials参数是必须的

fetch('/login', {
            method: 'POST',
            credentials: 'same-origin',
            body: JSON.stringify({password})
        }).then(res => res.json())
        .then(data => {
            if(data.status.code == 1001){
                // Modal.tips('登陆成功')
                history.back()
            }
            Modal.tips(data.result)
        })

ps: koa setCookie

this.cookies.set(key, value, options)
this.cookies.get(key)
LingYanSi commented 8 years ago

requirejs

简单实现


window.require = function(arr, func){
    let Arr = arr.map(item => require.fuck[item]())
    func.apply(window, Arr) 
}

window.require.fuck = {}

window.define = function(name, func){
    window.require.fuck[name] = func()
}
define('fuck', function(){
    return {
        name: 'xijinping'
    }
})

require(['fuck'], function($){
    console.log($) // {name: 'xijinping'}
})
LingYanSi commented 8 years ago

复写Ajax

此处使用闭包,可避免一些不必要的问题

(function(){
    var xx = $.ajax

    $.ajax = function( option ){
        let success = option.success

        option.success = function(data){
            if(data.succc) {
                console.log(`1`)
            } else {
                success && success(data)
            }
        }

        return xx(option)
    }
})() 

另一种bad的写法

$._ajax = $.ajax

$.ajax = function( option ){
    let success = option.success

    option.success = function(data){
        if(data.succc) {
            console.log(`1`)
        } else {
            success && success(data)
        }
    }

    return $._ajax(option)
}

以上代码一般没有问题,不过单纯从为$添加了一个不必要的方法来说就不太好 2016-9-23 遇到了一个问题,在上述代码执行两边的时候,代码进入了死循环

$._ajax = $.ajax

$.ajax = function( option ){
    let success = option.success

    option.success = function(data){
        if(data.succc) {
            console.log(`1`)
        } else {
            success && success(data)
        }
    }
    // 第二部,而此时原本的$._ajax指向了函数自身,因此进入死循环
    return $._ajax(option)
}

$._ajax = $.ajax

$.ajax = function( option ){
    let success = option.success

    option.success = function(data){
        if(data.succc) {
            console.log(`1`)
        } else {
            success && success(data)
        }
    }
    // 第一步
    return $._ajax(option)
}

$.get('/sss/sss')

上面的问题,在第一种闭包写法终究不会出现

LingYanSi commented 7 years ago

Array

数组去重

function uniqueArray(array){
    var n = [];//临时数组
    for(var i = 0;i < array.length; i++){
        if(n.indexOf(array[i]) == -1) n.push(array[i]);
    }
    return n;
}
LingYanSi commented 7 years ago

encodeURIComponent 与 encodeURI的区别

encodeURIComponent 会把字符串转译成一个url可用的参数 key=vakue encodeURI把字符串转成一个可用的url,不会转译:/+&=

encodeURIComponent是encodeURI的超集

看这里