文章写于 2016 年,旧的博客不维护了,一些文章直接迁移到这边来。现在看当时自己还是很青涩的哈哈,不管是文笔还是前端。文章的第二篇,记得应该是阿里的二面
Angular双向绑定的实现
嗯…面试三次,每个面试官都会问我这个问题,这里还是贴一下参考的文章吧:
Angular沉思录(一) 数据的双向绑定
AngularJS 数据双向绑定揭秘
简易实现版本:
var Scope = function () {
this.?watchers = [];
}
Scope.prototype.$watch = function( watchExp, listener ) {
this.?watchers.push( {
watchExp: watchExp,
listener: listener || function () {}
});
};
Scope.prototype.$digest = function() {
var dirty;
do {
dirty = false;
for (var i = this.?watchers.length - 1; i >= 0; i--) {
var newValue = this.?watchers[i].watchExp(),
oldValue = this.?watchers[i].last;
if( oldValue !== newValue) {
this.?watchers[i].listener(newValue, oldValue);
dirty = true;
this.?watchers[i].last = newValue;
}
};
} while(dirty);
};
var $scope = new Scope();
$scope.name = 'Ryan';
$scope.$watch(function () {
return $scope.name;
}, function ( newValue, oldValue ) {
console.log('Input Value has update:' + newValue + ' and Old Value is: ' + oldValue);
element[0].value = newValue;
tips.innerHTML = newValue
});
/** 视图到模型 **/
var element = document.querySelectorAll('input'),
tips = document.querySelectorAll('#tips')[0];
element[0].addEventListener('keyup', function () {
$scope.name = element[0].value;
$scope.$digest();
})
/** 模型到视图 **/
var updateScopeValue = function () {
$scope.name = 'Bob';
$scope.$digest();
}
var btn = document.getElementsByTagName('button')[0];
btn.addEventListener('click', function () {
updateScopeValue();
})
jQuery和Zepto的区别
jQuery: 历史悠久,对PC端友好,体积相对于Zepto过大,但有丰富的插件支持和社区支持
Zepto: 专门为移动端定制,比如tap事件,体积小,一些功能没有jQuery那么完善,不支持链式调用,不支持高级选择器(可以用原生选择器再包装),插件比较少,和jQuery不兼容
贴一篇文章: zepto和jquery的区别,zepto的不同使用8条小结 啊,属性选择器是支持的=.= 之前一直以为不支持:
Zepto 的选择器表达式: [name=value] 中value 必须用 双引号 “ or 单引号 ‘ 括起来 例如执行:
(‘[data-userid=”123123123]”‘) or $(“[data-userid=’123123123’]”)
觉得其他比较明显的不同是:
- 不能自定义事件;但可以:$('').bind('my', function(){});
- 选择selected和checked用prop方法 其他在上面的文章写的挺清楚的.但是一般还是用了jQuery了哈哈哈
JavaScript原生事件
感觉自己运气真好..面试前有比较仔细的看了这部分.看的是红色的那本JavaScript高级程序设计,讲的很明白很透彻:
事件流
从页面中接受事件的顺序 IE:事件冒泡 Netscape:事件捕获 DOM事件流: 捕获阶段,处于目标阶段,事件冒泡阶段(高版本浏览器会在捕获阶段触发事件)
事件处理程序
- HTML事件,函数有局部变量event,this等于事件目标元素;紧密耦合,时差问题
- DOM0级,btn.onclick = function () {};this引用当前元素,在冒泡阶段处理,删除通过 btn.onclick = null;
- DOM2级,addEventListener,第三个参数:true:捕获阶段调用,false:冒泡阶段调用;可以添加多个处理程序,按顺序触发,this指向当前元素,用false兼容大部分浏览器
- IE:attachEvent,冒泡,作用域为全局作用域,this为window,顺序相反
事件对象
- DOM&HTML: event对象:this指向currentTarget,target包含事件的实际目标;用type处理多个事件;eventPhase确定处于哪个阶段,从1开始
- IE:DOM0级:window.event,attach:event。用event.srcElement比较保险(attach中this是window);阻止:returnValue = false;cancelBubble = false
如何改变this的指向
面试的时候想到了函数绑定bind.面试官让我写出来=.=啊当时就比较慌了.想了一下,觉得还是说自己会的就好,就说了用apply或者call来实现.后面翻了一下书也确实是这么写的:
function bind(fn, context) {
return function () {
return fn.apply(context, arguments);
};
}
函数绑定要创建一个函数,可以在特定的this环境中以指定参数调用另一个函数.该技巧常常和回调函数与事件处理程序一起使用,以便在将函数作为变量传递的同事保留代码执行环境
var handler = {
message: "Event handled",
handleClick: function (event) {
alert(this.message);
}
};
var btn = document.getElementById('my-btn');
EventUtil.addHandler(btn, "click", bind(handler.handleClick, handler));
//Event handled
//ES5:
EventUtil.addHandler(btn, "click", handler.handleClick.bind(handler));
只要是将某个函数指针以值的形式进行传递,同时该函数必须在特定环境中执行,就需要这个绑定函数.
需要克隆元素并绑定之前所有的事件/移除一个元素所有绑定的事件/让事件执行的顺序都相同?
这个之前没想过,但是有看到一篇文章说这个. 感觉是会维护一个数组,数组保存着所有用户自己定义的事件,然后克隆的时候直接遍历这个数组绑定事件/移除事件.让事件执行顺序相同就根据浏览器(IE),逆序绑定事件达到所有事件执行顺序都相同. 说是这么说,也不知道是不是真的这么干,明天查查资料.断网啦睡觉啦.~~
Node的IO的了解
这个真不了解=.= 下面摘抄自<<深入浅出Nodejs>>
在Node中,除了JavaScript是单线程外,Node自身其实是多线程的,只是I/O线程使用的CPU较少.另一个需要重视的观点是,除了用户代码无法并行执行外,所有的I/O(磁盘I/0和网络I/O)则是可以并行起来的.
Node的执行模型包括:事件循环,观察者,请求对象,I/O线程池
JavaScript的代码通过调用C++核心模块进行下层的操作.
从JavaScript调用Node的核心模块,核心模块调用C++内建模块,内建模块通过libuv进行系统调用;libuv有两个平台的实现,实际上调用uv_fs_open()方法;
在uv_fs_open()调用过程中,创建了一个FSReqWrap请求对象,JS层传入的参数和方法都封装在这个请求对象中,回调函数是oncomplete_sym:
req_wrap->object_->Set(oncomplete_sym, callback);
包装完毕后,Windows下调用QueueUserWorkItem()将这个FSReqWrap对象推入线程池中等待执行.
至此,由JavaScript层面发起的异步调用第一阶段就此结束.JavaScript线程可以继续执行当前任务的后续操作,I/O操作就在线程池中等待执行.达到异步的目的.
执行回调:线程池中的IO操作调用完毕后,通过PostQueuedCompletionStatus()通知IOCP(IO完成端口),提交执行状态,并将线程归还线程池.
这个过程中,事件循环的IO观察者都会检查线程池中是否有执行完的请求,如果存在,将请求对象加入队列,作为事件处理.
IO观察者的回调函数就是取出请求对象的result属性作为参数,oncomplete_sym作为方法,调用执行.达到调用JavaScript中传入的回调函数的目的.
有张图好想贴上来!!就在书上~~ 看多几遍大概了解这个工作流程了.
Cookie与Session的区别
- cookie数据存放在客户的浏览器上,session数据放在服务器上;
- cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session;
- session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能。考虑到减轻服务器性能方面,应当使用COOKIE;
- 单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能超过3K;