《前端JavaScript面试技巧》笔记一
思考:
- 拿到一个面试题,你第一时间看到的是什么 -> 考点
- 又如何看待网上搜出来的永远也看不完的题海 -> 不变应万变
- 如何对待接下来遇到的面试题 -> 题目到知识再到题目
知识体系:
JS基础知识
一、变量类型和计算
题目:
- JS中使用typeof能得到哪些类型?
- 何时使用 === 何时使用 == ?
- JS中有哪些内置函数
- JS变量按照存储方式区分为哪些类型,并描述其特点
- 如何理解JSON
知识点:
/*一、变量类型*/
/*值类型vs引用类型*/
//从内存来说,值类型是把每个值分块存放在内存中,而引用类型是好几个变量公用一个内存块,节省内存空间。
//引用类型包括:对象、数组、函数。引用类型的属性是可以无限扩展的,属性多了,就会占用更多的内存空间,所以引用类型是为了公用内存空间。
//值类型
var a = 100;
var b = a;
a = 200;
console.log(b); //100
//引用类型
var a = {age:20};
var b = a;
b.age = 21;
console.log(a.age); //21 /*typeof运算符详解*/
//typeof只能区分值类型,引用类型也只能区分function,因为function的定位非常高。
typeof undefined //undefined (值类型)
typeof 'abc' //string (值类型)
typeof 123 //number (值类型)
typeof true //boolean (值类型)
typeof {} //object (引用类型)
typeof [] //object (引用类型)
typeof null //object (引用类型)
typeof console.log //function (引用类型) /*二、变量计算---强制类型转换*/
//字符串拼接
var a = 100+10; //110
var b = 100+'10'; //'10010'
//运算符
//==会把两边的值转换为true或false
100 == '100'; //true
0 == ''; //true
null == undefined; //true
//if语句
//if会把括号里面的值转换为true或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
//判断一个变量会被当作true还是false
var a = 100;
console.log(!!a);
解题:
JS中使用typeof能得到哪些类型?
undefined、string、number、boolean、object、function
何时使用 === 何时使用 == ?
if(obj.a==null){
//这里相当于 obj.a === null || obj.a ===undefined ,简写形式
//这是 jquery 源码中推荐的写法
}
双等会进行强制类型转换,三等不会进行强制类型转换。
除了上面的例子用双等,其它的都用三等。
JS中有哪些内置函数
数据封装类对象
Object
Array
Boolean
Number
String
Function
Date
RegExp :正则表达式
Error
JS变量按照存储方式区分为哪些类型,并描述其特点
值类型和引用类型。
从内存来说,值类型是把每个值分块存放在内存中,而引用类型是好几个变量公用一个内存块,节省内存空间。
如何理解JSON
JSON只不过是一个JS对象,也是一种数据格式。
JSON基本的api只有两个:
JSON.stringify({a:10,b:20}); //对象转字符串
JSON.parse('{"a":10,"b":20}'); //字符串转对象
二、原型和原型链
题目:
- 如何准确判断一个变量是数组类型
- 写一个原型链继承的例子
- 描述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',22); //创建多个对象
//new时把参数传进去。new函数执行时里面的this会变成空对象,给this赋值后,再把this给return回来,return回来就把值赋值给了f,这时f就具备f.name = 'zhangsan',f.age = 20,f.class ='' 'class-1' /*二、构造函数-扩展*/
/*
var a = {} 其实是 var a = new Object() 的语法糖。 构造函数是Object函数。
var a = [] 其实是 var a = new Array() 的语法糖。 构造函数是Array函数。
function Foo(){...} 其实是 var Foo = new Function(...)。 构造函数是Function。
推荐前面的书写方式。
使用instanceof判断一个函数是否是一个变量的构造函数。比如:判断一个变量是否为“数组”:变量 instanceof Array
*/
/*三、原型规则和示例*/
//5条原型规则-原型规则是学习原型链的基础
//1、所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了null以外)
var obj = {}; obj.a = 100;
var arr = []; arr.a = 100;
function fn(){}; fn.a = 100;
//2、所有的引用类型(数组、对象、函数),都有一个__proto__属性,属性值是一个普通的对象。 __proto__ 隐式原型
console.log(obj.__proto__);
console.log(arr.__proto__);
console.log(fn.__proto__);
//3、所有的函数,都有一个prototype属性,属性值也是一个普通的对象。 prototype显式原型
console.log(fn.prototype);
//4、所有的引用类型(数组、对象、函数),__proto__属性值指向它的构造函数的"prototype"属性值。
console.log(obj.__proto__ === Object.prototype);
//5、当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的 __proto__(即它的构造函数的prototype)中寻找。
//构造函数
function Foo(name,age){
this.name = name;
}
Foo.prototype.alertName = function(){
alert(this.name);
}
//创建示例
var f = new Foo('zhangsan');
f.printName = function(){
console.log(this.name);
}
//测试
f.printName(); //zhangsan
f.alertName(); //zhangsan //补充 -- 循环对象自身的属性
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(){
alert(this.name);
}
//创建示例
var f = new Foo('zhangsan');
f.printName = function(){
console.log(this.name);
}
//测试
f.printName(); //zhangsan
f.alertName(); //zhangsan
f.toString(); //要去f.__proto__.__proto__中查找 /*五、instanceof*/
//用于判断引用类型属于哪个构造函数的方法
//构造函数
function Foo(name,age){
this.name = name;
}
Foo.prototype.alertName = function(){
alert(this.name);
}
//创建示例
var f = new Foo('zhangsan');
f.printName = function(){
console.log(this.name);
}
//测试
f.printName(); //zhangsan
f.alertName(); //zhangsan
f.toString(); //要去f.__proto__.__proto__中查找 //instanceof
//f instanceof Foo 的判断逻辑是:
//1、f 的 __proto__ 一层一层往上,能否对应到 Foo.prototype
//2、再试着判断 f instanceof Object
解题:
如何准确判断一个变量是数组类型
var arr = [];
arr instanceof Array; //true
typeof arr; //object typeof是无法判断是否是数组的
写一个原型链继承的例子
//动物
function Animal(){
this.eat = function(){
console.log('animal eat');
}
} //狗
function Dog(){
this.bark = function(){
console.log('dog bark');
}
}
Dog.prototype = new Animal();
//哈士奇
var hashiqi = new Dog(); /*面试时千万不要写这个例子,要写更贴近于实战的原型链例子*/
/*用下面的例子*/
//写一个封装DOM查询的例子
function Elem(id){
this.elem = document.getElementById(id);
}
Elem.prototype.html = function(val){
var elem = this.elem;
if(val){
elem.innerHTML = val;
return this; //链式操作
}else {
return elem.innerHTML;
}
}
Elem.prototype.on = function(type,fn){
var elem = this.elem;
elem.addEventListener(type,fn);
return this;
}
var div1 = new Elem('div1');
console.log(div1.html());
div1.html('<h2>新内容</h2>').on('click',function(){
alert(div1.html());
}).html('<h2>新内容新内容新内容</h2>').on('click',function(){
alert('第二次');
}); //链式操作
/*div1.html('<h2>新内容</h2>')
div1.on('click',function(){
alert(div1.html());
})*/
描述new一个对象的过程
/*
1、创建一个新对象
2、this指向这个新对象
3、执行代码,即对this赋值
4、返回this
*/
/*构造函数*/
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',22); //创建多个对象
zepto(或其他框架)源码中如何使用原型链
- 阅读源码是高效提高技能的方式。如zepto
- 但不能“埋头苦钻”,有技巧在其中
- 慕课网搜索“zepto设计和源码分析”
三、作用域和闭包
题目:
- 说一下对变量提升的理解
- 说明this几种不同的使用场景
- 创建10个<a>标签,点击时弹出对应的序号
- 如何理解作用域
- 实际开发中闭包的应用
知识点:
/*一、执行上下文*/
//范围:一段<script>或者一个函数
//全局:变量定义、函数声明(一段<script>)
//函数:变量定义、函数声明、this、arguments(函数)
//PS:注意“函数声明”和“函数表达式”的区别
//实际代码中不要下面这种写法,都是先定义,再执行,提高代码可读性。
console.log(a); //undefined
var a = 100; fn('zhangsan'); //'zhangsan' 20
function fn(name){ //函数声明
age = 20;
console.log(name,age);
var age;
}
var fn = function(){} //函数表达式 /*二、this*/
//this要在执行时才能确认值,定义时无法确认。
//作为构造函数执行
//作为对象属性执行
//作为普通函数执行
//call、apply、bind
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 /*作用域*/
/*无块级作用域*/
//没有块级作用域,写在里面和外面是一样的。不建议下面这种写法,程序不易读。
if(true){
var name = 'zhangsan';
}
console.log(name); //zhangsan
/*函数和全局作用域*/
var a = 100; //全局变量
function fn(){
var a = 200; //局部变量
console.log('fn',a);
}
console.log('global',a);
fn(); /*作用域链*/
//函数的父级作用域是函数定义时的作用域,不是函数执行时的作用域。
var a = 100;
function fn(){
var b = 200; //当前作用域没有定义的变量,即“自由变量”
console.log(a); //100
console.log(b); //200
}
fn();
//例子
var a = 100;
function F1(){
var b = 200;
function F2(){
var c = 300;
console.log(a); //100 //自由变量
console.log(b); //200 //自由变量
console.log(c); //300
}
F2();
}
F1(); /*闭包*/
function F1(){
var a = 100; //返回一个函数(函数作为返回值)
return function(){
console.log(a);
}
}
//f1得到一个函数
var f1 = F1();
var a = 200;
f1();
//f1执行的是return里的函数,return里的a是个自由变量,要去父级作用域寻找,父级作用域F1里面定义了a,所以打印出来的a的值是100.
/*闭包的使用场景
1、函数作为返回值(上一个demo)
2、函数作为函数传递(下面这个例子)
*/
function F1(){
var a = 100;
return function(){
console.log(a);
}
}
var f1 = F1();
function F2(fn){
var a = 200;
fn();
}
F2(f1);
解题:
说一下对变量提升的理解
变量定义
函数声明(注意和函数表达式的区别)
执行上下文的概念。
各个函数中,它的变量的声明和定义,以及函数的声明都会提前,放在前面,由此就是变量提升主观上、形象上的理解。
说明this几种不同的使用场景
作为构造函数执行
作为对象属性执行
作为普通函数执行
call、apply、bind
创建10个<a>标签,点击时弹出对应的序号
var i;
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);
}
如何理解作用域
要领:
1、自由变量
2、作用域链,即自由变量的查找
3、闭包的两个场景
实际开发中闭包的应用
//闭包实际应用中主要用于封装变量,收敛权限
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 //在 isFirstLoad 函数外面,根本不可能修改掉 _list 的值
四、异步和单线程
题目:
- 同步和异步的区别是什么?分别举一个同步和异步的例子
- 一个关于setTimeout的笔试题
- 前端使用异步的场景有哪些
知识点:
/*什么是异步(对比同步)*/
//同时执行,不会阻塞程序执行
console.log(100);
setTimeout(function(){
console.log(200);
},1000);
console.log(300);
setTimeout(function(){
console.log(400);
},1000);
//下面这个例子类似同步
console.log(100);
alert(200);
console.log(300); /*前端使用异步的场景*/
/*何时需要异步:
在可能发生等待的情况
等待过程中不能像alert一样阻塞程序进行
因此,所有的“等待的情况”都需要异步
1、定时任务:setTimeout、setInterval
2、网络请求:ajax请求、动态<img>加载
3、事件绑定
*/
//ajax请求代码示例
console.log('start');
$.get('./data1.json',function(data1){
console.log(data1);
})
console.log('end');
//<img>加载示例
console.log('start');
var img = document.createElement('img');
img.onload = function(){
console.log('loaded');
}
img.src = '/xxx.png';
console.log('end');
//事件绑定示例
console.log('start');
document.getElementById('btn1').addEventListener('click',function(){
alert('clicked');
})
console.log('end'); /*异步和单线程*/
console.log(100);
setTimeout(function(){
console.log(200);
});
console.log(300);
//执行结果:100、300、200
//setTimeout是异步,最后执行。这个例子的setTimeout没有等待时间,所以待其它执行完之后立马执行setTimeout。
//单线程就是一次只能做一件事
/*解析:
1、执行第一行,打印100
2、执行setTimeout后,传入setTimeout的函数会被暂存起来,不会立即执行(单线程的特点,不能同时干两件事)
3、执行最后一行,打印300
4、待所有程序执行完,处于空闲状态时,会立马看有没有暂存起来的要执行。
5、发现暂存起来的setTimeout中的函数无需等待时间,就立即拿过来执行。
*/
解题:
同步和异步的区别是什么?分别举一个同步和异步的例子
同步会阻塞代码执行,而异步不会。
alert是同步,setTimeout是异步。
例子:
//异步
console.log(100);
setTimeout(function(){
console.log(200);
},1000);
console.log(300);
//同步
console.log(100);
alert(200);
console.log(300);
一个关于setTimeout的笔试题
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
前端使用异步的场景有哪些
- 定时任务:setTimeout、setInterval
- 网络请求:ajax请求、动态<img>加载
- 事件绑定
五、其它知识点
题目:
- 获取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){
//遍历数组的所有元素。item:元素的值。index:元素的位置
console.log(index,item);
})
//every //判断所有元素是否都符合条件
var arr = [1,2,3];
// var arr = [1,2,3,4,5];
var result = arr.every(function(item,index){
if(item<4){
return true;
}
})
console.log(result); //true
//some //判断是否有至少一个元素符合条件
var arr = [1,2,3];
var result = arr.some(function(item,index){
if(item<2){
return true;
}
})
console.log(result); //true
//sort //排序
var arr = [1,4,2,5,3];
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);
//filter //过滤符合条件的元素
var arr = [1,2,3,4];
var arr2 = arr.filter(function(item,index){
if(item>=2){
return true;
}
})
console.log(arr2); /*对象API*/
var obj = {
x:100,
y:200,
z:300
}
var key;
for(key in obj){ //key是obj的属性名
//注意这里的 hasOwnProperty ,再讲原型链时候讲过了
if(obj.hasOwnProperty(key)){ //判断key是obj原生的属性,而不是原型里面的属性
console.log(key,obj[key]);
}
}
解题:
获取2017-06-10格式的日期
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 formatDate = formatDate();
console.log(formatDate);
获取随机数,要求是长度一致的字符串格式
var random = Math.random();
var random = random + '0000000000'; //后面加上10个零,为了确保长度一致
var random = random.slice(0,10); //截取前10位
console.log(random);
写一个能遍历对象和数组的通用forEach函数
function forEach(obj,fn){
var key;
if(obj instanceof Array){
//准确判断是不是数组
obj.forEach(function(item,index){
fn(index,item);
})
}else{
//不是数组就是对象,对象用for in循环
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(obj,function(key,value){
console.log(key,value);
})
《前端JavaScript面试技巧》笔记一的更多相关文章
- JavaScript高级程序设计笔记之面向对象
说起面向对象,大部分程序员首先会想到 类 .通过类可以创建许多具有共同属性以及方法的实例或者说对象.但是JavaScript并没有类的概念,而且在JavaScript中几乎一切皆对象,问题来了,Jav ...
- javascript高级程序设计--笔记01
概述 JavaScript的实现包含三个部分: 1 核心(ECMAScript) 提供核心语言功能 2 文档对象模型(DOM) 一套提供了访问以及操作网页内容的API 3 浏览器对象模型( ...
- javascript事件小结(事件处理程序方式)--javascript高级程序设计笔记
1.事件流:描述的是从页面中接收事件的顺序. 2.事件冒泡:IE的事件流叫做事件冒泡,即事件开始从具体的元素(文档中嵌套层次最深的那个节点)接收,然后逐级向上传播到不具体的节点(文档). 3.事件捕获 ...
- JavaScript高级程序设计笔记(一)
---恢复内容开始--- 前三章为基础知识,为了方便以后查看,所以比较啰嗦.这里对函数的基本操作没有记录. 1.JavaScript的实现 虽然 JavaScript 和 ECMAScript 通常都 ...
- JavaScript高级程序设计笔记 事件冒泡和事件捕获
1.事件冒泡 要理解事件冒泡,就得先知道事件流.事件流描述的是从页面接收事件的顺序,比如如下的代码: <body> <div> click me! </div> & ...
- <javascript高级程序设计>笔记
1.要讲一个值转换成其对应的Boolean类型 ,可以调用转型函数Boolean(). var message=“hello world!”; var messageAsBoolean=Boolean ...
- javaScript高级程序设计笔记 2
Undefinde Null Boolean Number String 基本类型 Object 引用类型 只有引用类型才能动态的添加属性 赋值基本类型和引用类型也不相同,复制的基本类型的 ...
- javaScript高级程序设计笔记 1
核心 ECMAScript 文档对象模型 DOM 浏览器对象模型 BOM 延迟脚本 defer typeof操作符 判断字符类型 返回 undefined boolean s ...
- Javascript高级程序设计笔记 <第五章> 引用类型
一.object类型 创建object实例的方式有两种: //第一种使用new操作符跟构造函数 var person= new Object(); person.name="小王" ...
- Javascript高级程序设计笔记(很重要尤其是对象的设计模式与继承)
var obj = {'a':'a'}; var fun = function (){} console.log(typeof obj);//object console.log(typeof fun ...
随机推荐
- iOS 将Excel导入到SQLite3的过程
1.打开Excel表格,另存为.csv文件 2.打开SQLite3,选择File -> Import -> other... 3.在弹出的文件选择框中选择步骤1保存的.cvs文件 4在弹出 ...
- str.split()与re.split()的区别
str.split(): >>>'hello, world'.split() >>>['hello,','world'] >>>'hello, w ...
- vux 使用 font-awesome
1)XIcon 太多坑,不好用,无奈之下,搞了一下 font-awesome 2)下载 font-awesome 源码,并放置到 根目录/src 目录下 ,传送门:http://fontawesome ...
- MVC的初步认识理论
说起来写博客可以说一个月没来啦,我们狠狠的放假一个月,想一想都奇怪.而是想一下以后的假期还会这样吗?或许这是作为学生的我们的最后一个长的假期啦,以后就要面对工作再也没有寒假暑假之分啦,在这一个月的时间 ...
- 【摘抄】C++程序员练级攻略
摘抄自互联网文章 作为C++程序员,或者说程序员一定要提升自己: 专访李运华:程序员如何在技术上提升自己-CSDN.NET专访徐宜生:坚决不做代码搬运工!-CSDN.NET 上面两个文章我觉得都不错. ...
- .net页面生命周期【转】
.Net 页面生命周期IIS 所收到的对某 Microsoft ASP.NET 页面的每个请求都被移交给 ASP.NET HTTP 管线.HTTP 管线由一系列托管对象组成,这些对象按顺序处理该请求, ...
- windows“启动”对应的路径
C:\Users\huangye\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
- Android设计和开发系列第一篇:Notifications通知(Develop—API Guides)
Notifications IN THIS DOCUMENT Design Considerations Creating a Notification Required notification c ...
- vuex - 辅助函数学习
官网文档: https://vuex.vuejs.org/zh-cn/api.html 最底部 mapState 此函数返回一个对象,生成计算属性 - 当一个组件需要获取多个状态时候,将这些状态都声 ...
- JS笔记 - JQ事件委托( 适用于给动态生成的脚本元素添加事件)
最近一段时间打了一个大仗,现在总算消停点,才有时间来做个总结吧算是: 移动端遇到一个项目,是一个列表的侧滑栏,在我这里用jq写的交互事件.自测各方面都挺好的,美滋滋的给了研发.研发也美滋滋的开始开发. ...