一、基礎知識
1.變量類型和計算
題目:
- js中使用typeof能獲得的類型有哪些
- 什麼時候使用===什麼時候使用==
- js中有哪些內置函數
- js變量按照存儲方式分爲哪些類型,並描述其特色
- 如何理解json
知識點:
1.變量類型:值類型與引用類型
值類型:
var a=100;
var b=a;
a=200;
console.log(b);//100
引用類型:對象、數組、函數
var a={age:20};
var b=a;
b.age=21;
conlose.log(a.age)//21
typeof運算符:只能區分值類型的詳細類型
typeof undefined //undefined
typeof 'abc' //string
typeof 123 //number
typeof true //boolean
typeof {} //object
typeof [] //object
typeof null //object
typeof console.log //function
2.變量計算
強制類型轉換:
- 字符串拼接
var a=100+10; //110
var b=100+'10'; //'10010'
- ==運算符 (0、‘’、null、undefined都會轉換成false)
null==undefined; //true
100=='100'; //true
0=''; //true
- if語句 (0、‘’、null、undefined都會轉換成false)
var a=true
if(a){...}
var b=100
if(b){...}
var c=''
if(c){...}
- 邏輯運算
console.log(10&&0) ; //0
console.log(''||'abc') ; //'abc'
console.log(!window.abc); //true
var a=100;
console.log(!!a); //true
解答:
- undefined/string/number/boolean/object/function
- 參考jquery源碼:
if(obj.a==null){
//至關於obj.a===null || obj.a===undefined 簡寫
}除此外,其餘都用===
- 內置函數(數據封裝類對象):Object Array Boolean Number String Function Date RegExp Error
- 值類型和引用類型
- json 只不過是一個 JS 對象而已,也是一種數據格式
- JSON.stringify({a:10,b:20}) 將對象轉換爲字符串
- JSON.parse('{"a":10,"b":20}') 將字符串變爲對象
2.原型與原型鏈
題目:
- 如何準確判斷一個變量是數組類型
- 寫一個原型鏈繼承的例子
- 描述new一個對象的過程
- zepto(或其餘框架)源碼中如何使用原型鏈
知識點:
- 構造函數(函數名首字母大寫)
function Foo(name,age){
this.name=name;
this.age=age;
this.class='class-1';
// return this //默認有這一行
}
var f=new Foo('zhangsan',20);
var f1=new Foo('lisi',23);
- 構造函數-擴展
var a={} 實際上是var a=new Object()的語法糖;
var a=[]實際上是var a=new Array()的語法糖;
funtion() Foo(){...}實際上是var Foo=Function(){...};
使用instanceof判斷一個函數是不是一個變量的構造函數;
- 原型規則和示例
5條原型規則,原型規則是原型鏈的基礎。
- 全部的引用類型(數組對象函數),都具備對象特性,便可自由擴展屬性(除’null‘之外);
- 全部的引用類型,都有一個_proto_屬性,屬性值是一個普通的對象;
- 全部函數,都有一個prototype屬性,屬性值是一個普通的對象;
- 全部引用類型,_proto_屬性值指向(徹底等===)他的構造函數的prototype屬性值;
- 當試圖獲得一個對象的某個屬性時,若果這個對象自己沒有這個屬性,那麼它的_proto_(即它的構造函數的prototype)中尋找。
示例:
1.原則i
var obj={};obj.a=100;
var arr=[];arr.a=100;
function fn(){};fn.a=100;
2.原則ii
console.log(obj._proto_);
console.log(arr._proto_);
console.log(fn._proto_);
3.原則ii
console.log(fn.prototype);
4.原則iv
console.log(obj._proto===Object.prototype)
5.原則v
function() Foo(name,age){
this.name=name;
}
Foo.prototype.alertName=function(){...}
var f=new Foo('zhangsan');
f.printName=function(){...}
f.printName();
f.alertName();
循環對象自身屬性
var item;
for(item in f){
//高級瀏覽器已經在for in 中屏蔽了來自原型的屬性,但這裏建議你們加上這個判斷,保 證程序的健壯性
if(f.hasOwnProperty(item)){
console.log(item)
}
}
- 原型鏈
function() Foo(name,age){
this.name=name;
}
Foo.prototype.alertName=function(){...}
var f=new Foo('zhangsan');
f.printName=function(){...}
f.printName();
f.alertName();
f.toString(); 要去f._proto_._proto_中查找
- instanceof
用於判斷引用類型屬於哪一個構造函數的方法。
f instanceof Foo 判斷邏輯是:
f的_proto_一層一層網上,可否對應到Foo.prototype;
再試着判斷f instanceof Object
解答:
1.var arr=[]
arr instanceof Array //true
typeof arr //object,typeof是沒法判斷數組的
2.原型鏈繼承的例子
基礎例子:
function Animal(){
this.eat=function(){}
}
function Dog(){
this.bark=function(){}
}
Dog.prototype=new Animal()
var hashiqi=new Dog()
3.建立一個對象,this指向這個新對象,執行代碼即對this賦值,返回this,構造函數知識點。
4.慕課網搜索 zepto設計和源碼分析
3.做用域和閉包
注:聲明的變量和函數會被提高
//全局
console.log(a);
var a=100;
fn('zhangsan');
function fn(name){
//函數
console.log(this);
console.log(arguments);
age=20;
console.log(name,age);
var age
bar(100);
function bar(name){
console.log(name)
}
}
題目
- 說一下變量提高的理解
- 說明this幾種不一樣的使用場景
- 建立10個<a>標籤,點擊的時候彈出來對應的序號
- 如何理解做用域
- 實際開發中閉包的應用
知識點
- 執行上下文(聲明提高)
console.log(a);//undefined
var a=100;
fn('zhangsan'); //'zhangsan',20
function fn(name){
age=20;
console.log(name,age);
var age;
}
範圍:一段<script>或者一個函數
全局:變量定義、函數聲明、一段<script>
函數:變量定義、函數聲明、this、arguments、函數
注意:函數聲明和函數表達式的區別
- this
this要在執行時才能肯定值,定義時沒法確認
var a={
name:'A',
fn:function(){
console.log(this.name);
}
}
a.fn(); // this===a
a,fn.call({name:'B'}); // this==={name:'B'}
var fn1=a.fn;
fn1(); //this===window
做爲構造函執行
function Foo(name){
this={};
this.name=name;
return this;
}
var f=new Foo('zhangsan');
做爲對象屬性執行
var obj={
name:'A',
printName:funtion(){
console.log(this.name);
}
}
obj.printName();
做爲普通函數執行
function fn(){
console.log(this); //this===window
}
fn();
call apply bind
function fn(name){
alert(name);
console.log(this); //this===window
}
fn.call({x:100},'zhangsan');
- 做用域
沒有塊級做用域
只有函數和全局做用域
//無塊級做用域
if(true){
var name='zhangsan'; //提高到if外面
}
console.log(name); //'zhangsan'
//函數和全局做用域
var a=100;
function fn(){
var a=200;
console.log('fn',a);
}
console.log('global',a);//全局 100
fn(); //函數 200
- 做用域鏈
var a=100
function fn(){
var b=200;
//當前做用域沒有定義的變量,即「自由變量」
console.log(a);//去父級做用域取值,聲明時的父做用域
console.log(b)
}
- 閉包
function F1(){
var a=100;
//返回一個函數(函數做爲返回值)
return function(){
console.log(a);//去父級做用域取值,聲明時的父做用域
}
}
var f1=F1();
var a=200;
f1();//100
使用場景:函數做爲返回值,函數做爲參數傳遞
解答
1.變量定義、函數聲明提高
2.構造函數、對象屬性、普通函數、call apply bind
3.
var i,a
for(i=0;i<10;i++){
(function(i){
var a=document.createElement('a');
a.innerHTML=i+'<br>';
a.addEventListener('click',function(e){
e.preventDefault();
alert(i)
})
document.body.appendChild(a);
})(i)
}
4.自由變量 做用域鏈,即自由變量的查找 閉包的兩個場景
5.閉包實際應用主要用於封裝變量,收斂權限
function isFirstLoad(){
var _list=[];
return function(id){
if(_list.indexof(id)>=0){
return false
}else{
_list.push(id);
return true;
}
}
}
var firstLoad=isFirstLoad();
firstLoad(10); //true
firstLoad(10); //false
firstLoad(20); //true
4.異步和單線程
題目
- 同步和異步的區別是什麼?分別舉例
- 一個關於setTimeout的筆試題
- 前端使用異步的場景有哪些
知識點
什麼是異步(對比同步)有沒有阻塞
異步:無阻塞
console.log(100)
setTimeout(function(){
console.log(200)
},1000)
console.log(300)
輸出:100 300 200
同步:有阻塞
console.log(100)
alert(200) //幾秒後點擊確認
console.log(300)
前端使用異步的場景
在可能發生等待的狀況,等待過程當中不能像alert同樣阻塞程序運行,所以,全部的等待的狀況都須要異步。
- 定時任務setTimeout setInverval
- 網絡請求:ajax請求,動態<img>加載
- 事件綁定
異步和單線程
單線程的特色:不能同時幹兩件事。
解答
同步會阻塞代碼執行,而異步不會。
console.log(1)
setTimeout(function(){
console.log(2)
},0)
console.log(3)
setTimeout(function(){
console.log(4)
},1000)
console.log(5)
輸出:1 3 5 2 4 異步須要等待,因此2是5輸出後纔會執行
其餘知識
題目
- 獲取2017-06-10格式的日期
- 獲取隨機數,要求是長度一致的字符串格式
- 寫一個能遍歷對象和數組的通用forEach函數
知識點
日期
Date.now() //獲取當前時間毫秒數
var dt=new Date()
dt.getTime() //獲取毫秒數
dt.getFullYear() //年
dt.getMonth() //月(0-11)
dt.getDate() //日(0-31)
dt.getHours() //小時(0-23)
dt.getMinutes() //分鐘(0-59)
dt.getSeconds() //秒(0-59)
Math
獲取隨機數Math.random() 0-1之間
數組API
forEach:遍歷全部元素
var arr=[1,2,3]
arr.forEach(function(item,index){//值,索引
//遍歷數組的全部元素
console.log(index,item)
})
every:判斷全部元素是否都符合條件 返回true或false
var arr=[1,2,3]
var result=arr.every(function(item,index){
//用來判斷全部的數組元素,都知足一個條件
if(item<4){
return true
}
})
console.log(result)
some:判斷是否有至少一個元素符合條件 返回true或false
var arr=[1,2,3]
var result=arr.some(function(item,index){
//用來判斷全部的數組元素,只要有一個知足條件便可
if(item<2){
return true
}
})
console.log(result)
sort:排序,改變原數組
var arr=[1,4,2,3,5]
var arr2=arr.sort(function(a,b){
//從小到大
return a-b
//從大到小
return b-a
})
console.log(arr2)
map:對元素從新組裝,生成新數組
var arr=[1,2,3,4]
var arr2=arr.map(function(item,index){
//將元素從新組裝,並返回
return '<b>' +item+'</b>'
})
console.log(arr2)
fileter:過濾符合條件的元素,返回符合條件的數組
var arr=[1,2,3]
var arr2=arr.filter(function(item,index){
//經過某一個條件過濾數組
if(item>=2){
return true
}
})
console.log(arr2)
對象API
for in
var obj={
x:100,
y:200,
z:300
}
var key
for(key in obj){//key就是obj的屬性名,即x,y,z
//注意這裏的hasOwnProperty,在講原型鏈時候講過
if(obj.hasOwnProperty(key)){
console.log(key,obj[key])
}
}
解答
function formatDate(dt){
if(!dt){
dt=new Date();
}
var year=dt.getFullYear();
var month=dt.getMonth()+1;
var date=dt.getDate();
if(month<10){
month='0'+month;
}
if(date<10){
date='0'+date;
}
return year+'-'+month+'-'+date;
}
var dt=new Date();
var date=formatDate(dt);
console.log(date);
var random=Math.random()
var random=random+'0000000000' //後面加10個零
var random=random.slice(0,10)
console.log(random)
function forEach(obj,fn){
var key
if(obj instanceof Array){
//判斷是否爲數組
obj.forEach(function(item,index)){
fn(index,item)
}
}else{
//不熟數組就是對象
for(key in obj){
fn(key,obj[key])
}
}
}
var arr=[1,2,3]
forEach(arr,function(index,item){
console.log(index,item)
})
var obj={
x:100,
y:200
}
forEach(arr,function(key,value){
console.log(key,value)
})