面试题笔记
程序员文章站
2022-06-09 17:20:15
...
HTML && CSS
如何理解HTML语义化?
- 让人更容易读懂代码 (增加代码可读性)
- 让搜索引擎更容易读懂
默认情况下,哪些HTML标签是块级元素,哪些是内联元素?
- display: block/table,有div、p、h1~h6、table、ul、ol等
- inline/inline-block,有input、img、span、button等
offsetWidth
- offsetWidth = (Width + padding + border),无margin
- box-sizing:border-box; => offsetWidth的值 = width的值
margin纵向重叠问题
- 相邻元素的mg-top和mg-bottom会发生重叠 (取最大值)
- 中间空白内容的标签也会重叠 (会忽略)
margin负值
- margin-top和margin-left负值,元素向上、向左移动
- margin-right负值,右侧元素向左移动,自身不受影响
- margin-bottom负值,下方元素上移,自身不受影响
BFC(块级格式化上下文)1
形成BFC的条件:
- Float不是none
- Position是absolute或fixed
- Overflow不是visible
- Display是flex/inline-block等
BFC的常见应用:清除浮动
- (父元素和第一个兄弟元素分类加上overflow: hidden;就能触发BFC来清除浮动)
float布局
- 圣杯布局和双飞翼布局的目的
- 三栏布局,中间一栏最先加载和渲染( 内容最重要 )
- 两侧内容固定,中间内容随着宽度自适应
- 一般用于PC网页
- 圣杯布局和双飞翼布局的技术总结
- 使用float布局
- 两侧使用margin负值,以便和中间内容横向重叠
- 防止中间内容被两侧重叠,一个用padding一个用margin
手写clearfix
.clearfix:after {
content: “”;
display: table;
clear: both;
}
.clearfix { zoom: 1; }
relative 和 absolute定位
- relative依据自身定位
- absolute依据最近一层定位元素 ((relative fixed absolute) || body) 定位
居中对齐的实现方式
- 水平对齐
- Inline:text-align: center;
- block:margin: auto;
- absolute:left: 50% + margin-left负值
- 垂直对齐
- Inline:line-height的值 = height值
- absolute:top: 50%; + margin-top负值
- absolute:transform: translate(-50%, -50%);
- absolute: top,left,right,bottom = 0 + margin: auto;
line-height如何继承
- 具体数值:如30px,则继承该值
- 比例:如2/1.5,则继承该比例
- 百分比:如200%,则继承计算出来的值 (考点)
长度单位
- px:绝对长度单位,最常用
- em,相对长度单位,相对于父元素,不常用
- rem,相对长度单位,相对于根元素(html),常用于响应式布局
JS变量与原型链
JS中使用typeof能得到的类型是什么?
String、number、undefined、boolean、object、function (object和function为引用类型)
graph LR
A[typeof] --> |null| B[object]
A --> |console.log| C[function]
何时使用 === 何时使用 ==
if( obj.a == null ) {}
- 等同于obj.a === null || obj.a === undefined,简写形式
- 此为jquery源码中推荐的写法
JS中有哪些内置函数 –数据封装类对象
Object、Array、Boolean、Number、String、Function、Date、RegExp和Error
如何理解JSON
JSON只不过是一个 对象 而已
JSON.stringify() JSON.parse()
JS变量按照存储方式区分为哪些类型,并描述其特点?
可分为 值类型 和 引用类型
- 值类型是存储在栈中的简单数据,它们的值直接存储在变量访问的位置。
- 引用类型是存储在堆中的对象,存储在变量处的值是一个指针,指向存储对象的内存处。
判断一个变量是true还是false,可用双逻辑非运算符 ( !!a )
描述 new 一个对象的过程:
- 创建一个新对象
- this指向这个新对象
- 执行代码,即对this赋值
- return this
构造函数-扩展
- var a = {};其实是var a = new Object();的语法糖
- var a = [];其实是var a = new Array();的语法糖
- function fn() {};是var fn = new Function();的语法糖
- 使用instanceof判断一个函数是否是一个变量的构造函数
原型规则
- 所有的引用类型(对象、数组、函数),都具有对象特性,即可*扩展属性(除”null”之外)
- 所有的引用类型(对象、数组、函数),都具有一个__proto__(隐式原型)属性,属性值是一个普通的对象
- 所有的函数,都具有一个prototype(显式原型)属性,属性值也是一个普通的对象
- 所有的引用类型(对象、数组、函数),__proto__属性值指向它的构造函数”prototype”属性值
- 当试图得到一个对象的某个属性时,如果这个对象中没有这个属性,那么会去它的__proto__(即它的构造函数的prototype)中寻找
原型属性注意点
高级浏览器已经在for in屏蔽了来自原型的属性
建议加上这个判断,保证程序的健壮性
for(var item in f){
if(f.hasOwnProperty(item)){
console.log(item);
}
}
对象的hasOwnProperty方法检测一个属性是否来自对象的自有属性,而不是从原型链中继承的
一个贴近原型链继承的例子
写一个封装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 div = new Elem('div1');
div.html('<p>hello imooc!</p>').on('click',function(){
alert('clicked')
});
作用域与闭包
说一下对变量提升的理解:
在js脚本代码执行之前,会先创建一个全局执行上下文环境2
- 范围:一段 script 标签或者一个函数
- 全局:变量定义、函数声明
- 函数:变量定义、函数声明、this、arguments
函数声明 与 函数表达式的区别:
// 函数声明
fn('Lisa'); // 声明之前调用不会报错
function fn(name){
age = 18;
console.log(name, age);
var age;
}
// 函数表达式
fn1(); // 会报错,因为fn1是一个变量,暂先赋值为undefined
var fn1 = function() {
window.alert('hello');
}
说明以下this的几个使用场景:
this在执行时才能确认值,定义时无法确认
// 作为构造函数
function Fn(name){
this.name = name;
}
var fn = new Fn('zhangsan')
// 作为对象的属性
var obj = {
name: 'A',
printName: function(){
console.log(this.name)
}
}
//作为普通函数
function person(){
console.log(this)
}
person() // window
// call apply bind
function fcf(name, age){
alert(name)
console.log(this)
}
fcf.call({name: 'Aa'}, '张三', 18) // name: 'Aa'
创建10个a标签,点击时弹出相应地序号
for(var i = 1;i<=10;i++){
(function(i) {
/*自执行函数,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 fn(){
var a = 100
return function (){
console.log(a)
}
}
// fnn得到一个function
var fnn = fn();
var a = 200
fnn() // 100
// 函数作为参数传递
function f1(){
var a = 100
return function (){
// a *变量 像父级作用域去寻找,函数**定义时的作用域
console.log(a)
}
}
var F1 = f1()
function f2(fn){
var a = 200
fn()
}
f2(F1)
闭包实际应用中主要用于封装变量、收敛权限
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
firstLoad(20) //false
JS异步单线程与内置对象
同步和异步的区别是什么?分别举一个同步和异步的例子
- 同步会阻塞代码执行,而异步不会
- 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
- 网络请求:axaj请求、动态加载
- 事件绑定
数组API
- forEach() 遍历所有元素
- every() 判断所有元素是否都符合条件
- some() 判断元素是否有至少一个元素符合条件
- sort() 排序 ( a-b || b-a )
- map() 对元素重新组装,生成新数组
- filter() 过滤符合条件的元素
取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
}
console.log( formatDate(new Date()) )
获取随机数,要求是长度一致的字符串格式
var random = Math.random()
random = random + '0000000000'
// 取随机数0-10位
random = random.slice(0, 10)
写一个能遍历对象和数组的通用forEach函数
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,3,5,9]
forEach(arr, function(index, item){
console.log(index, item)
})
var obj = {x:10, y:20}
forEach(obj, function(key, val) {
console.log(key, val)
})
DOM、BOM与事件
常说的JS( 浏览器执行的JS )包含两部分:
- JS基础知识(ECMA262标准)
- JS-Web-API( W3C标准 )
DOM操作的常用API有哪些?
- 获取DOM节点,以及节点的property和Attribute
- 获取父节点,获取子节点
- 新增节点、删除节点
DOM属于数据结构中的树
DOM节点的Attribute和property有何区别?
- property只是一个JS对象的属性的修改
- Attribute是对html标签属性的修改
如何检测浏览器的类型?
var ua = navigator.userAgent
var isChrome = ua.indexOf('Chrome')
console.log(isChrome)
拆解url的各部分
// location
console.log(location.href) // url
console.log(location.host) // 域名
console.log(location.protocol) // 协议
console.log(location.search) // ?开头
console.log(location.hash) // #开头
编写一个通用的事件监听函数
function bindEvent(elem, type, selector, fn) {
if(fn == null) {
fn = selector
selector = null
}
elem.addEventListener(type, function(e) {
var target
if(selector) {
// 代理
target = e.target
// matches判断DOM节点是否能完全匹配对应的css选择器
if(target.matches(selector)) {
fn.call(target, e)
}
}else {
// 不是代理
fn(e)
}
})
}
var div1 = document.getElementById('div1')
bindEvent(div1, 'click', 'a', function(e) {
// 使用代理
console.log(this.innerHTML)
})
var p1 = document.getElementById('p1')
bindEvent(p1, 'click', function(e) {
// 不适用代理
console.log(p1.innerHTML)
})
描述事件冒泡流程
- DOM树形结构
- 事件冒泡
- 阻止冒泡
- 冒泡的应用
对于一个无限下拉加载图片的页面,如何给每个图片绑定事件
使用事件代理
代理的两个优点:代码简洁;减少事件注册,提高性能
跨域的几种实现方式
- JSONP
- 服务器端设置http header
跨域
- 浏览器有同源策略,不允许ajax访问其他域接口
- 跨域条件:协议、域名、端口,有一个不同就算跨域
- 允许跨域加载资源的三个标签
- <img src=” ”>
http请求状态码(status)
- 2xx – 表示成功处理请求,如200
- 3xx – 需要重定向,浏览器直接跳转
- 4xx – 客户端请求错误,如404
- 5xx – 服务器端错误