总结一些前端基础的知识,有些知识可能在前端面试的时候会问到,所以做个记录,也有助于其他人查看,如果有什么问题,可以指出,会积极修正。
变量类型和计算
JS中typeof的类型有哪些
console.log(typeof undefined); //undefined
console.log(typeof 123); //number
console.log(typeof '123'); //string
console.log(typeof true); //boolean
console.log(typeof [1,2,3]); //object
console.log(typeof {"id": 11}); //object
console.log(typeof null); //object
console.log(typeof console.log); //function
类型转换
- 显式类型转换
- Number 函数
- 数字:转换后还是数字
- 字符串:如果可以被解析为数值,则为相应的数值,如果不能,则是 NaN,如果是空字符串那就是0
- 布尔值:true为1,false为0
- undefined:NaN
- null:0
- object:先执行valueOf,看是否能转换,如果不可以再执行toString,看是否可以转换,如果不可以报错
- String 函数
- 数字:转换成对应的字符串
- 字符串:还是对应的字符串
- 布尔值:true为'true',false为'false'
- undefined:undefined
- null:null
- object:先执行toString,看是否能转换,如果不可以再执行valueOf,看是否可以转换,如果不可以报错
- Boolean
下面这几个是false,其他都是true- NaN
- null
- undefined
- 0
- ""
- false
- Number 函数
- 隐式类型转换
- 四则运算
- 判断语句
- 奇葩的类型转换面试题
何时使用==
,何时使用===
除了obj.a == null
以外,都用===
,==
要用的时候一定要是已经定义的obj.a == null
转换之后其实是 obj.a == null || obj.a == undefined
JS中有哪些内置函数
Object
Array
Boolean
Number
String
Function
Date
RegExp
Error
JS变量按照存储方式有哪些类型
- 1.值类型
- 2.引用类型(节省空间,公用内存块)
区别:值类型改变一个不会影响其他的,引用类型改变都改变,因为公用内存块
如何理解JSON
JSON是JS的一个对象,也是一种数据格式,JSON中的两个api如下
- 将JSON字符串转换成JSON对象
JSON.parse()
- 将JSON对象转换成JSON字符串
JSON.stringify()
使用Object.prototype.toString
获取一个对象的类型
var toString = Object.prototype.toString;
toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]
toString.call(/s/); // [object RegExp]
toString.call([]); // [object Array]
//Since JavaScript 1.8.5
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]
原型和原型链
原型的五条规则
- 所有的引用类型都可以自定义添加属性
- 所有的引用类型都有自己的隐式原型(proto)
- 函数都有自己的显式原型(prototype)
- 所有的引用类型的隐式原型都指向对应构造函数的显示原型
- 使用引用类型的某个自定义属性时,如果没有这个属性,会去该引用类型的__proto__(也就是对应构造函数的prototype)中去找
如何准确判断一个变量是数组类型
arr instanceof Array
instanceof判断一个引用类型是什么引用类型,是通过__proto__(隐式原型一层一层往上找,能否找到对应构造函数的prototype)
写一个原型链继承的例子
function Element(ele) {
this.ele = document.getElementById(ele);
}
Element.prototype.html = function(val) {
var ele = this.ele;
if (val) {
ele.innerHTML = val;
return this;
} else {
return ele.innerHTML;
}
};
Element.prototype.on = function(type, fn) {
var ele = this.ele;
ele.addEventListener(type, fn);
return this;
}
var element = new Element('main');
element.html('hello').on('click', function() {
alert('handleClick');
});
描述new一个对象的过程
- 创建一个新对象
- this指向这个新对象
- 执行代码给this赋值
- return this
function Foo(name) {
this.name = name;
// return this; // 本身会执行这一步
}
var f = new Foo('shiyanping');
作用域及闭包
变量提升
以下两种情况会进行提升:
- 变量定义
- 函数说明
this几种不同的使用场景
- 在构造函数中使用(构造函数本身)
- 作为对象属性时使用(调用属性的对象)
- 作为普通函数时使用(window)
- call,apply,bind(执行的第一个参数)
var a = {
name: 'A',
fun: function() {
console.log(this.name);
}
};
a.fun(); //this === a
a.fun.call({ name: 'B' }); //this === { name: 'B' }
var fun1 = a.fun;
fun1(); //this === window
创建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);
}
如何理解作用域
- 自由变量
- 作用域链,及自由变量的查找,找不到逐级向上找
- 闭包的两个场景
- 函数作为变量传递
- 函数作为返回值
实际开发中闭包的应用
// 判断一个数字是否出现过
function isFirst() {
var _list = [];
return function(id) {
if (_list.indexOf(id) >= 0) {
return false;
} else {
_list.push(id);
return true;
}
};
}
var first = isFirst();
first(10);
first(10);
first(20);
单线程和异步
同步和异步的区别,分别列举一个同步和异步的例子
同步会阻塞代码,但是异步不会 alert是同步 setTimeout是异步
关于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加载
- 事件绑定
需要等待的情况下都需要异步,因为不会像同步一样阻塞
日期和Math
知识点:
日期
console.log(Date.now()); // 获取当前毫秒数
var dt = new Date(); // 获取当前时间
console.log(dt.getTime()); // 当前时间的毫秒数
console.log(dt.getFullYear()); // 年
console.log(dt.getMonth()+1); // 月(0-11)
console.log(dt.getDate()); // 日(0-31)
console.log(dt.getHours()); // 时(0-23)
console.log(dt.getMinutes()); // 分(0-59)
console.log(dt.getSeconds()); // 秒(0-59)
Math
Math.random()
- 返回 0 ~ 1 之间的随机数Math.abs(x)
- 返回数的绝对值Math.ceil(x)
- 向上取整Math.floor(x)
- 向下取整
常用的数组api
- forEach(遍历所有元素)
var arr = ['a', 'b', 'c', 'd'];
arr.forEach(function (item, index) {
console.log(item + ',' + index);
})
- map(对数组进行重新组装,生成新的数组)
// map,生成新数组,不改变原来数组的格式
var arr = ['a', 'b', 'c', 'd'];
var result = arr.map(function (item, index) {
return index + '/' + item;
})
console.log(result);
- sort(对数组进行排序)
// sort, 会改变原来数组
var arr = [1, 23, 3, 4];
var result = arr.sort(function (a, b) {
// 从小到大排序
return a - b;
// 从大到小排序
// return b - a;
})
console.log(result);
- filter(过滤符合条件的元素)
var arr = [1, 2, 3, 4];
var result = arr.filter(function (item, index) {
if (item < 3) {
return true
}
})
console.log(result);
- every(判断所有元素是否都符合要求)
var arr = [1, 2, 3, 4];
var result = arr.every(function (item, index) {
if (item < 3) {
return true
}
})
console.log(result); // false
- some(判断是否有至少一个元素符合条件)
var arr = [1, 2, 3, 4];
var result = arr.some(function (item, index) {
if (item < 3) {
return true
}
})
console.log(result); // true
- join(根据条件对数组组合成字符串)
var arr = [1, 2, 3, 4];
var result = arr.join(',');
console.log(result);
- reverse(将数组反转)
var arr = [1, 2, 3, 4];
var result = arr.reverse();
console.log(result);
常用的对象api
- for in
- hasOwnProperty(检查属性是不是对象自有的,排除从原型链找到的属性)
var obj = {
x: 10,
y: 20,
z: 30
}
for (var key in obj) {
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 nowDate = new Date();
var formatDate = formatDate(nowDate);
console.log(formatDate);
获取随机数,要求长度一致的字符串格式
function randomStr(len) {
var random = Math.random();
random = random + '0000000000'; // 防止自动生成的数字不满足长度报错并且强制转换成字符串
return random.substr(0, len)
}
console.log(randomStr(20));
写一个能遍历对象和数组的通用forEach函数
function forEach(obj, fn) {
if (obj instanceof Array) {
obj.forEach(function (item, index) {
fn(index, item);
})
} else {
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
fn(key, obj[key]);
}
}
}
}
var arr = [1, 2, 3, 4];
forEach(arr, function (index, item) {
console.log(index + ',' + item);
});
var obj = {
x: 10,
y: 20
};
forEach(obj, function (index, item) {
console.log(index + ',' + item);
});