Open LingYanSi opened 9 years ago
在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。 如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。
在计算机科学中,闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。 --- 维基百科
其实这段引用已经说明了闭包的本质:引用了自由变量的函数,自由变量将和这个函数一同存在——这是理解闭包的关键。 这里有篇博客
改变作用域链,但性能较低,不建议使用。
return跳出的当前程序所在的环境 比如说
function bitch(){
console.log('aaa');
return ;
}
function eva(){
bitch();
console.log('bbb')
}
eva(); // --> aaa
// --> bbb
URL中是search在前还是hash在前?
其中?search=a这种叫query,#hash叫fragment。
- query的规定是以第一个?开始,至行尾或#结束。
- fragment以#为开始,行尾为结束。 也就是说query必须在fragment之前。
另外根据query和fragment字符限定的规定,两者中都可以含有/和?,但不可以含有#。(还有其它的限制,这里是简要的说法,因为我们此处要讨论以?和#开头的字串)
几次面试都被问到,知不知道前端模板,用没用过。 说到模板,我一直以为都是像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 这么做用着还算不错。
先这样吧,去吃饭了
今天在给商品编辑添加功能时候,看到了PubSub这么个字符,是什么东西不太清楚 没有问菲哥,自己看了看,似乎是类似于【事件注册与派发】
function func(msg, data) {
console.log(msg, data)
}
//事件注册
PubSub.subscribe('here.update', func);
//触发事件
PubSub.publish('here.update', {
data: '数据过来咯'
});
有时间了,自己造一个 PubSubJS
在React中,有的时候组建嵌套太深,或者不相干的组件,需要通信传递数据 使用PubSub就可以方便的解决问题
lodash 适用于现代浏览器 ie9及其以上,也有全兼容的版本 underscore 兼容全部
因为【数组/字符串/函数/对象】等在不同浏览器上,所含有的属性、方法不同,比较新的特性老的浏览器上自然不支持 他们就像jquery磨平了浏览器的兼容性,可使用相关最新的es6特性,并且有所扩展。 但为什么不使用babel编译呢?只能所各有所长了
mgj,这边会在每次请求的时候,根据传递过来的cookie,来验证用户是否有权限进行相关操作。 cookie的读写由后端决定。这样做很爽。
久闻函数式编程,今天再看阮一峰的博文时,看到一个很好的例子
var obj = {
fun : function(){
console.log('我是方法')
}
};
obj.fun() ; // 这是函数式
delete obj.fun ; // 这是命令式
Promise的队列与setTimeout的队列的有何关联? 在JS中只有一个时间循环,但可以有多个任务队列
_macrotask_:script(整体代码)、setTimeout、setInterval、setImmediate _microtask_:promise(浏览器原生实现的)、process.nextTick(node)
浏览器执行时会 1.先从macrotask队列中取出第一个任务执行,执行完毕后从microtask队列中取出所有任务执行。 2.再从macrotask队列中取出第二个任务执行,再从microtask队列中取出所有任务执行。 如此这般。
突然想到一个捷径
var a = {name:'嘿嘿'};
var b = JSON.parse( JSON.stringify(a) );
直接上码
<!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>
Error
: 基类型。EvalError
: 使用eval()函数发生异常时抛出。RangeError
: 数值超出相应范围时抛出。ReferenceError
: 找不到对象时抛出。SyntaxError
: 使用eval()函数中的字符串有语法错误时抛出。TypeError
: 在变量中保存意外类型或访问不存在的方法时抛出。URIError
: 使用encodeURI或decodeURI()中URI格式不正确时抛出。try{
// 如果return了就不会执行catch
return 1
throw new Error('我是你爹')
}catch(e){
console.log(e.message,e.name) // message错误信息 name错误类型
return 2
}finally{
// finally 会一直执行
return 3
}
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)
}
}
}
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)'})
经常会遇到一种状况:发起一个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)
}
})(),
}
使用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)
简单实现
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'}
})
此处使用闭包,可避免一些不必要的问题
(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')
上面的问题,在第一种闭包写法终究不会出现
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;
}
js常用框架/库
d3
etc