2016 實習招聘面試經歷 - 2

文章寫於 2016 年,舊的博客不維護了,一些文章直接遷移到這邊來。如今看當時本身仍是很青澀的哈哈,無論是文筆仍是前端。文章的第二篇,記得應該是阿里的二面javascript

Angular雙向綁定的實現

嗯…面試三次,每一個面試官都會問我這個問題,這裏仍是貼一下參考的文章吧:
Angular沉思錄(一) 數據的雙向綁定
AngularJS 數據雙向綁定揭祕
簡易實現版本:html

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條小結 啊,屬性選擇器是支持的=.= 以前一直覺得不支持:java

Zepto 的選擇器表達式: [name=value] 中value 必須用 雙引號 「 or 單引號 ‘ 括起來 例如執行:(‘[data-userid=123123123]’)  
結果:Error: SyntaxError: DOM Exception 12  
解決辦法:(‘[data-userid=」123123123]」‘) or $(「[data-userid=’123123123’]」)jquery

以爲其餘比較明顯的不一樣是:web

  • 不能自定義事件;但能夠:$('').bind('my', function(){});
  • 選擇selected和checked用prop方法 其餘在上面的文章寫的挺清楚的.可是通常仍是用了jQuery了哈哈哈

JavaScript原生事件

感受本身運氣真好..面試前有比較仔細的看了這部分.看的是紅色的那本JavaScript高級程序設計,講的很明白很透徹:面試

事件流

從頁面中接受事件的順序 IE:事件冒泡 Netscape:事件捕獲 DOM事件流: 捕獲階段,處於目標階段,事件冒泡階段(高版本瀏覽器會在捕獲階段觸發事件)數組

事件處理程序

  1. HTML事件,函數有局部變量event,this等於事件目標元素;緊密耦合,時差問題
  2. DOM0級,btn.onclick = function () {};this引用當前元素,在冒泡階段處理,刪除經過 btn.onclick = null;
  3. DOM2級,addEventListener,第三個參數:true:捕獲階段調用,false:冒泡階段調用;能夠添加多個處理程序,按順序觸發,this指向當前元素,用false兼容大部分瀏覽器
  4. IE:attachEvent,冒泡,做用域爲全局做用域,this爲window,順序相反

事件對象

  1. DOM&HTML: event對象:this指向currentTarget,target包含事件的實際目標;用type處理多個事件;eventPhase肯定處於哪一個階段,從1開始
  2. 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;

參考文章:理解Cookie和Session機制

相關文章
相關標籤/搜索