我是蒟蒻,大佬求放过
尝试定义一个复制函数,接受上图所示的类似结构(只有一个根节点),返回一个全新的结构相同的对象
考点:数据结构
这题应该是定义一个可以复制二叉树的函数,不过数据结构目前还没学到这…
请使用尽可能多的CSS选择器及伪类选中如下的"I love bingyan",并将其变为红色(规则主体可只写一次)
考点:CSS选择器
上方的代码由自己补全:
<html>
<head>
<style>
/* 元素选择器 span{} √
* id选择器 #{} √
* 类选择器 .{] √
* 通配选择器 *{} ×
* 交/并集选择器,子元素,后代,兄弟 此处不考虑
* 重点练习伪类选择器:(child和type的区别见下方)
*/
span:first-child{
color:red;
}
span:first-of-type{
color:red;
}
span:nth-child(1){
color: red;
}
span:nth-of-type(1){
color: red;
}
style>
head>
<body>
<div class="hello" id="world" data-love="yes">
<p>
DO NOT SELECT ME.
p>
<span>
I love bingyan.
span>
div>
body>
html>
css选择器中:first-child与:first-of-type的区别:总的来说,child系匹配结构上的第n个子元素,type系匹配的是某父元素下相同类型子元素中的第一个。
请用图形方式展现如下CSS代码产生的盒模型及尺寸
考点:CSS盒子模型,border-box
<style>
div{
margin: 10px 20px 30px;
padding-top: 20px;
padding-left: 10px;
padding-right: 10px;
width: 100px;
height: 100px;
box-sizing: border-box;
}
style>
三个方向的margin,分别代表:上、左右、下
(擅自加了背景颜色和边框,右侧为content-box对比版)
由于一般情况下padding的值默认为0,又没有设置padding-bottom,所以padding-bottom == 0,而height == 100 - 20 = 80px
使用HTML和CSS实现一个双栏等宽布局
考点:HTML和CSS实现网页布局
首先来了解一下什么是“双栏布局”,这个布局方式见过,但这个名词我还没听说过:kokodayo
用box-shadow将两栏隔开
!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<style>
.wrapper{
width: 1210px;
margin: 100px auto;
}
.box1{
width: 600px;
height: 400px;
margin-right: 10px;
box-shadow: 1px 1px 5px rgba(0, 0, 0, .3);
float: left;
}
.box2{
width: 600px;
height: 400px;
box-shadow: 1px 1px 5px rgba(0, 0, 0, .3);
float: left;
}
style>
head>
<body>
<div class="wrapper">
<div class="box1">div>
<div class="box2">div>
div>
body>
html>
列出在JavaScript中可以选中HTML元素的方法,他们的返回值分别是什么类型
突然想到一个问题:type="text/javascript"是必须的吗:kokodayo
列出你所知道的JavaScript基本类型
USONB you are so niubility (滑稽)
u undefined
s string symbol
o object(引用类型)
n null number
b boolean
继续思考,怎么对object进行分类:kokodayo
请思考如何在网页中显示一个三角形,列出尽可能多的方法(请放飞自我)
请参考我的这篇博客:kokodayo
不过里面只有两种方法,最常见的方法估计还是第一种
列出尽可能多的专用于创建一个表单的HTML元素(如table,tr)
w3school表格
w3school表单
table、tbody、td、tr、th(表头)
form、input、button
表单的属性众多:
(表单相关内容在学习了nodejs后再复习更佳)
如何让一个元素相对其父元素垂直居中
可以参考:HTML/CSS 实现居中的方法
方法一:绝对定位+margin
方法二:table-cell和align管垂直+margin管水平
方法三:绝对定位和平移
补充:方法四:弹性盒中的垂直居中
行内元素和块级元素有什么区别
列出在JavaScript中创建一个对象并给其增加一个可读取的属性的方法
先创建对象再设置属性:
var obj = new Object();
obj.attr1 = "attr1"
obj.attr2 = 1;
对象字面量:
var obj = {
attr1 = "attr1",
attr2 = 1;
}
JavaScript的Array和Object之间有什么关系
参考:JS对象分类
Array是Object,
Object是Array的原型,Array是Object的实例(更准确的说法是,Object.prototype是Array.prototype的原型,反过来是实例…)
参考:js中Object与Function与Array的关系图
特别喜欢这个博客说的一句话:万物皆对象,所有的函数都是function的实例
在JavaScript中使用new运算符创建一个对象的过程中发生了什么
参考博客1
参考博客2
数组的shift方法
阮一峰博客
过程四(+1)步走:
//一个简单的构造函数
function Rocker(name){
this.name = name;
};
Rocker.prototype.getName = function(){
return this.name;
}
var createObject = function(){
var obj = new Object(),
//(1)创建一个空对象
Constructor = [].shift.call(arguments);
//(2)shift方法会返回数组中的第一个元素,
//该语句的意思是,将传入的第一个参数(即构造函数对象,也就是下方的Rocker)赋值给Constrctor对象
//(因为prototype的constructor属性会指向该原型对象的构造函数,所以这里给变量起名为Constructor,不懂的去看阮一峰博客)
obj.__proto__ = Constructor.prototype;
//(3)把obj的原型链指向Constructor的原型
var ret = Constructor.apply(obj, arguments);
//(4)把参数传入Constructor(即Rocker)函数中,并把this修改为obj(修改上下文)
return typeof ret === 'object' ? ret : obj;
//(5)如果传参正确,就返回ret(正确的实例对象),否则返回空对象
};
var Freak = createObject(Rocker, 'Freak');
console.log(Freak.name); //Freak
console.log(Freak.getName()); //Freak
console.log(Object.getPrototypeOf(Freak) === Rocker.prototype); //true
计算返回值(已用console.log表示)
<script type="text/javascript">
console.log({
}=={
});//false
console.log([]==[]);//false
console.log([]==0);//true
console.log("0"==false);//true
</script>
空对象和空数组不相等的原因:kokodayo
思否:JavaScript 深入了解基本类型和引用类型的值
因为对象是引用类型,比较两个对象时,是引用的比较,两个对象的地址不一样,所以返回false。
如何将一个类数组对象转化为数组对象?如果想不转化便使用Array上定义的方法该如何做?
学习一下“伪数组”:
思否:伪数组(ArrayLike)
JavaScript中的数组与伪数组的区别
CSDN:如何把一个伪数组转化成真正的数组?
方法一:ES6的拓展运算符
const divs = document.querySelectorAll('div');
const divArr = [...divs];
console.log(divArr);
//即:var arr = [...arrLike];
方法二:遍历添加入一个空数组
var arr = [];
for(var i = 0; i < arrLike.length; i++){
arr.push(arrLike[i]);
}
方法三:ES6的Array.from方法
var arr = Array.from(arrLike);
方法四:slice()方法
var arr = [].slice.call(arrlike);
//对于call和apply,slice之前是[]或Array.prototype都可以
var arr = Array.prototype.slice.apply(arrlike);
以上几种方法,不会保留索引值以外的其他额外属性
方法五:修改原型指向
arrLike.__proto__ = Array.prototype;
这样arrLike就继承了Array.prototype中的方法,可以使用push(),unshift()等方法了,length值也会随之动态改变。
另外这种直接修改原型链的方法,还会保留下伪数组中的所有属性,包括不是索引值的属性。
<html>
<head>
<meta charset="UTF-8">
<title>title>
<style type="text/css">
div{
width: 100px;
height: 100px;
background-color: #bfa;
border-bottom: 3px solid black;
}
style>
<script>
window.onload = function(){
var arrlike = document.getElementsByClassName("box");
//var arrlike = document.getElementsByTagName("div");
//不要这么写,因为页面中有隐藏div,占用伪数组的第一个位置
console.log(arrlike);
console.log(arrlike instanceof Array);
var arr = Array.from(arrlike);
console.log(arr);
console.log(arr instanceof Array);
}
script>
head>
<body>
<div class="box">div>
<div class="box">div>
<div class="box">div>
<div class="box">div>
<div class="box">div>
<div class="box">div>
<div class="box">div>
<div class="box">div>
body>
html>
在测试这个例子的时候,发现以后应尽量避免使用getElementsByTagName(“div”)
用call或apply:
使用slice:
window.onload = function(){
var arrlike = document.getElementsByClassName("box");
//比如,此时想对伪数组使用slice方法
var arr = [].slice.call(arrlike,2,5);
var arr = Array.prototype.slice.call(arrlike,2,5);
var arr = [].slice.apply(arrlike,[2,5]);
var arr = Array.prototype.slice.apply(arrlike,[2,5]);
console.log(arr);
console.log(arr instanceof Array);
}
使用其他方法:在类数组中使用数组方法
我试图照猫画虎使用push(),但是一直在报错…
var myul = document.getElementById("myul");
Array.prototype.push.call(arrlike,myul);
这个地方先放着,我在网上查到的方式:
(function() {
Array.prototype.push.call(arguments, 4)
console.log(arguments)
// [1,2,3,4]/{ '0': 1, '1': 2, '2': 3, '3': 4 }
})(1,2,3)
但我照着写,发现还是失败了…
3.10 我回来了,这样写就ok了,之前是没理解call
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
<script>
window.onload = function () {
var arrlike = document.getElementsByClassName("box")
var arr = [].slice.call(arrlike).concat("Danmo")
// arr.push("Danmo") 输出结果正常
console.log(arr)
}
script>
head>
<body>
<div class="box">
div>
<div class="box">
div>
<div class="box">
div>
<div class="box">
div>
<div class="box">
div>
<div class="box">
div>
<div class="box">
div>
<div class="box">
div>
<div class="box">
div>
<div class="box">
div>
<div class="box">
div>
<div class="box">
div>
body>
html>
也可以先将伪数组转化为数组,再使用push,但这样不符合“伪数组使用数组方法”的题意
请写出以下代码的日志结果
阮一峰——学习Javascript闭包(Closure)
廖雪峰——闭包
考点:闭包
var fn = (function() {
var i = 1;
return function() {
console.log(i++);
}
})();
fn();
fn();
fn();
输出结果是:1 2 3
fn的返回值是一个匿名函数(它是函数中的函数,即闭包),它调用了变量i,导致fn第一次调用后产生的i还留在内存中
请描述let,const和var之间的区别,并解释暂时性死区的意义
可参考:
let,const和var之间的区别
阮一峰的ES6教程
var:变量可重复声明,无块级作用域,存在变量提升
let:变量不能重复声明,存在块级作用域,不存在变量提升
const:声明必须赋初值,不能重复声明,值不能修改,块级作用域,不存在变量提升
暂时性死区:如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
在代码块内,使用let命令声明变量之前,该变量都是不可用的。 这在语法上,称为“暂时性死区”。
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
请写出使用XMLHttpRequest发送一个GET请求的代码
参考:MDN
由于还没学ajax,暂时不能看懂
var xhr = new XMLHttpRequest();
xhr.open('GET', '/server', true);
xhr.onload = function () {
// 请求结束后,在此处写处理代码
};
xhr.send(null);
//XMLHttpRequest.send() 方法接受一个可选的参数,其作为请求主体;
//如果请求方法是 GET 或者 HEAD,则应将请求主体设置为 null
请简单描述一个请求从客户端发送出去的流转过程
参考:一个HTTP请求的曲折经历
(现在理解并不深入,学过计网后再看一遍吧)
如何对⼀个整数乱序数组进⾏排序?请写出代码或简单思路
选择排序和插入排序,之前的博客里有…这里先不写了,其他的排序方法还不是太熟悉…(简单的桶排序其实也可)
有如下的⼆维数据,请⽤最适当的数据结构进⾏描述并能够较好扩展,并⽤代码实现以下⽬的
emm,涉及数据结构的题目啊,先放着
- < img> 中⼀般都会有的属性是 () A. src B. alt C. title D. href
A
- ⿏标点击时超链接样式为 () A. a:link B. a:visited C. a:hover D. a: active
D
- 下⾯哪⼀个不是JavaScript基本类型 () A. symbol B. object C.array D. null
C
- (不定项)纯函数是⼀类没有副作⽤的函数,其输出结果只依赖其输⼊,以下关于 Array 的⽅法中你认为是纯函数的有哪些 () A. sort B. filter C. map D. reverse E. push F. pop G. every H. splice I. slice
CGI
这道题介绍了纯函数的概念,可参考博客:
JavaScript 数组纯函数
JS 数组详细操作方法及解析合集
菜鸟教程——Array every方法
(some和every类似,只不过some只要有一个符合条件就会返回true,而every要求全部符合条件)
菜鸟教程——Array map方法
(在原数组的基础上构建一个新数组)
可以简单认为,对原数组没有影响的方法就是纯函数
- 请尽可能多的写出你知道的html元素标签,并区分⾏内元素与块级元素
这篇博客概括得极为全面:行内元素和块级元素都有哪些
列举一些常见的块级元素和行内元素:
块级:div、nav、h1~h6、p、table、ul、ol、li、form
行内:a、span、i、em、img(易错)、input(易错)、br(易忽略)
- 请尽可能多的写出你知道的css 选择器
可参考:阮一峰——CSS选择器笔记
元素选择器、id选择器、类选择器、通配选择器、伪类选择器、复合选择器、交集选择器、并集选择器、子元素选择器、后代元素选择器、兄弟选择器、属性选择器(用得很少)
- 请尽可能多的写出引⽤css的⼏种⽅法,并区分其优先级
内联样式:在标签内style=" : ",比如:< body style=“background-color: gray”>
内部样式表:不必多言
外部样式表:不必多言,link引入
优先级:!improtant > 内联样式 > 内部样式表 > 外部样式表
- 请你写出合适的html、css,使⽤在(6)中写出的css 选择器来选择HTML元素,随意发挥
这题不想做Orz…
- 请写出以下代码的运⾏结果:
var a = 1;
function b(){
console.log(a);
var a = a + 1;
console.log(a);
}
b();
参考:廖雪峰——变量作用域与解构赋值
这篇博客里有句话值得关注:JavaScript的函数在查找变量时从自身函数定义开始,从“内”向“外”查找。如果内部函数定义了与外部函数重名的变量,则内部函数的变量将“屏蔽”外部函数的变量。
对于这道题,由于外部函数和内部函数都定义了a,而且内部函数是用var定义的,存在变量提升,也就是说,内部函数在初始化的时候a就赋值为undefined了…
所以输出结果是:undefined NaN(这题考的确实巧妙)
- 请说明以下输出的结果,并说明原因:
'use strict';
var maple = {
baz: 3
};
var foo = {
baz: 4,
bar: function(){
console.log(this);
for(var i = 0; i < this.baz; i++){
setTimeout(function(){
console.log(this,i);
});
}
}
};
foo.bar.bind(foo).call(maple);
先了解一下什么是“严格模式”吧:阮一峰——Javascript 严格模式详解
(严格模式下,有很重要的一条:禁止this关键字指向全局对象,菜鸟教程中说,在函数中,在严格模式下,this 是未定义的(undefined))
我们回到这道题,输出结果为:
foo对象
window对象
window对象
window对象
window对象
首先foo.bar.bind(foo)会把this值指定为foo,这个整体会成为新的函数
然后.call(maple)会调用这个新的函数,并再次把this值修改为maple(但实际上this的值还是为foo)
参考这篇博客:深入理解call、apply、bind(改变函数中的this指向)
注意:一旦函数通过bind绑定了有效的this对象,那么在函数执行过程中this会指向该对象,即使使用call、apply也不能改变this的指向
关于计时器呢,可以看看这篇博客:Javascript定时器中的this指向
如果没有特殊指向,setInterval和setTimeout的回调函数中this的指向都是window。这是因为JS的定时器方法是定义在window下的。
妙!又是一道好题!冰岩nb!
- 请⽤ es5 的语法实现JavaScript数组的find⽅法:
Array.prototype.myfind = function(fun){
for(var i=0;i<this.length;i++){
//误打误撞把this给用对了
if(fun(this[i]))
return this[i];
}
}
var ages = [3, 10, 18, 20];
function checkAdult(age) {
return age >= 18;
}
var foo = ages.myfind(checkAdult);
console.log(foo);//18
//测试后,和find的效果别无二致
- 简述undefined和not defined的区别。
可参考:javaScript中not defined,undefined和null的区别
总结一下,区别就是:undefined表示定义但未赋值,而not defined表示没有定义。用var声明变量时存在变量提升,此时也只是先声明变量但不给变量赋值。
- 你知道哪些 http method?返回状态码⾸位数字含义(1、2、3、4、5)。
返回状态码首位数字含义:
1** 信息。服务器收到请求,请继续执行请求
2** 成功。请求被成功接收并处理
3** 重定向。需要进一步操作来完成请求
4** 客户端错误。无法完成请求,或请求包含语法错误
5** 服务器错误。服务器在处理请求的过程中发成错误
- 请⽤你喜欢的⽅式向
https://google.com
发送⼀个 POST 请求,在请求体上附带上hello google
信息。
这题不会…
- 简述浏览器缓存的多种⽅法及其区别(从时效、特性等出发)
参考博客:简述浏览器端的九大缓存
http缓存
是基于HTTP协议的浏览器文件级缓存机制,针对文件的重复请求情况下,浏览器可以根据协议头判断从服务器端请求文件还是从本地读取文件websql
这种方式只有较新的chrome浏览器支持,并以一个独立规范形式出现。它是将数据以数据库的形式存储在客户端,根据需求去读取。跟Storage的区别是: Storage和Cookie都是以键值对的形式存在的;Web Sql 更方便于检索,允许sql语句查询,让浏览器实现小型数据库存储功能indexDB
是一个为了能够在客户端存储可观数量的结构化数据,并且在这些数据上使用索引进行高性能检索的 API,一般用户保存大量用户数据并要求数据之间有搜索需要的场景Cookie
一般网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)Localstorage
html5的一种新的本地缓存方案,目前用的比较多,一般用来存储ajax返回的数据,加快下次页面打开时的渲染速度。不适合存放过多的数据Sessionstorage
和localstorage类似,但是浏览器关闭则会全部删除,api和localstorage相同,实际项目中使用较少。application cache
是将大部分图片资源、js、css等静态资源放在manifest文件配置中,便于离线浏览网页cacheStorage
是在ServiceWorker的规范中定义的,可以保存每个serverWorker申明的cache对象flash缓存
这种方式基本不用,这一方法主要基于flash有读写浏览器端本地目录的功能再看一篇:浏览器缓存看这一篇就够了
- 你如何看待JavaScript ‘继承’?简要谈谈你的理解。
- 请写出以下内容的输出(环境限定为当前最新 lts 版 node, v8.12.0)
我希望再学一次event loop和promise,现在对异步JS编程的理解还是不够
console.log('script start'); // 同步代码 (1)
var foo = {
value: 'foo',
then: function () {
throw new Error('error in foo');
},
bar: function () {
return 'this is bar';
}
};
setTimeout(function () {
console.log('time out'); // timers阶段,执行setTimeout(6)
}, 0);
new Promise(function (res, rej) {
console.log('in promise'); //同步代码 (2)
setTimeout((function () {
//由于res的执行被延迟了,所以直接执行rej
res(foo);
return foo.bar;
})(), 0);
rej(new Error('error in promise')); //经测试,即便注掉这句,也不影响'error in foo'的输出
}).then(function (o) {
//不执行res,因此then中的代码不会生效
console.log('get promise val');
console.log(o.value);
})
.catch(function (err) {
//catch用于指定发生错误时的回调函数,和throw对应
console.log(err.message); //promise的then或catch,此处控制输出'error in foo' (5)
});
process.nextTick(function () {
console.log('next tick'); //遇到后event loop会停下来,立马执行,此处它会在第一个event loop开始之前执行 (4)
});
console.log('script end') //同步代码 (3)
- 你了解哪些有趣的前端或者互联⽹历史
网景公司和微软公司的较量,第一二次浏览器大战
- 选出下列四个选项中不是html标签的一项 A. tr B. td C. th D. tb
D
- 选出以下不为css属性的一项 A. font-color B. margin C. text-size D. z–index
我认为A和C都没有欸
- 以下哪项能获取到DOM中的第一个 元素? A. document.getElementById(“test”) B. document.getElementsByClassName(“test”)[0] C. dom.getElementById(“test”) D. dom.getElementByClassName(“test”)[0]
B
- JavaScript: 2 + “1” + 2 = ? A. “23” B. 5 C. “5” D. “212”
D
'+'两侧只要有一侧是字符串,另一侧的数字则会自动转换成字符串,因为其中存在隐式转换
- JavaScript: 2 / 0 = ? A. 报错 B. 0 C. infinity
C
- css有几种选择器(写不出名字可直接上代码)
- 写出所有你能想到的方法,在网页上呈现出一个三角形
这两题做过了~
- 写出对元素实现绝对(水平,垂直)居中布局的方式
margin,position:absolute,transform,display:table-cell,vertical-align:center…上边也说过了
- 指出以下两行代码的区别
var xiahao = new Person()
var xiahao = Person()
第二种方式,仅仅是把函数Person的返回值赋值给xiahao;
而第一种方式,xiahao成为构造函数Person的一个实例对象
- 写出常见的一些图片格式
参考:常用的几种图片格式
jpg、png、gif、psd、webp(限于chrome)
图片的格式:
jpeg(jpg)
gif
png
webp
base64
- 用HTML和CSS实现一个简单的等宽三栏式布局
之前写的双栏等宽布局是可以的,不过我发现width写成百分比的形式好像更符合题意:
<html>
<head>
<meta charset="UTF-8">
<title>title>
<style type="text/css">
.box1{
margin-top: 100px;
width: 33.33%;
height: 500px;
box-shadow: 3px 3px 5px rgba(0,0,0,.3);
float: left;
}
style>
head>
<body>
<div class="box1">div>
<div class="box1">div>
<div class="box1">div>
body>
html>
- 如何用JavaScript将字符串“abcdefg”变成”gfedcba”
这题考到了sort方法呀 ←No,字符串和数组是不一样的,sort失败了…
参考博客:
JavaScript字符串逆序(2种方法)
join方法
主要有如下两种方法:
//先将字符串用push存入一个数组,再将数组用join转化为字符串
var reverse = function( str ){
var stack = [];//生成一个栈
for(var len = str.length,i=len;i>=0;i-- ){
stack.push(str[i]);
}
return stack.join('');
};
//将字符串用split存入另一个数组,然后reverse,join一气呵成,干净利落(推荐)
var reverse = function( str ){
return str.split('').reverse().join('');
};
- 请写出以下输出日志结果,并解释。
for(var i = 0; i < 5; ++i){
setTimeout(function() {
console.log(i)
}, 500);
}
参考:JS中For循环中嵌套setTimeout()方法的执行顺序
结果:输出5次5
原因:定时器是一个异步函数,在执行它之前,先跑完for循环,所以定时器会在控制台输出5次5。
- 和2017年秋final stage前的那道题是一样的,考点为闭包
- 一个乱序数字数组长度为n,如[3,2,5,7…],如何将该数组按由大到小排序?尽量用多种方式。(不熟悉JavaScript可以直接用高中的那种流程框图表达思路)
传统的冒泡排序:
var array=[3,2,5,7];
console.log(array);//(4)[3,2,5,7]
bubbleSort(array,array.length);//冒泡排序
function bubbleSort(arr,n){
for(var i=1;i<n;i++){
for(var j=0;j<n-i;j++){
if(arr[j]>arr[j+1]){
var t=arr[j];
arr[j]=arr[j+1];
arr[j+1]=t;
}
}
}
}
console.log(array);//(4)[2,3,5,7]
传统的选择排序:
var array=[3,2,5,7];
console.log(array); //(4)[3,2,5,7]
selectSort(array,array.length);//选择排序
function selectSort(arr,n){
for(var i=0;i<n-1;i++){
for(var j=i,k=j+1;k<n;){
if(arr[j]<=arr[k]){
var min=j;
k++;
}
else{
var min=k;
j=k;
k++;
}
}
var t=arr[i];
arr[i]=arr[min];
arr[min]=t;
}
}
console.log(array);//(4)[2,3,5,7]
使用JS特色的sort方法:
var array=[3,2,5,7];
console.log(array);
array.sort(function(a,b){
return a-b;
})
console.log(array);
剩下几个聊天题就不做了
- 列举⾏内元素、块级元素各三个。
行内:a、span、img
块级:h1、p、div
- content-box 盒⼦模型结构如何?其与 border-box 有何区别?
- px,em,rem,vw 分别作何解释?
参考博客:px、em、rem、%、vw、vh、vm这些单位的区别
- display:none 与 visibility:hidden 有何区别
参考博客:visibility :hidden和display:none的区别
这篇博客说得很全面了,不过按我的经验,仅仅是:
- inline-block 的 vertical-align 属性默认是以下哪种对⻬?
middle 中线 baseline 基线 bottom 底线 top 顶线
当然是 baseline!
- rgba() 和 opacity 的透明效果在应⽤上有何不同?
参考博客:css透明度之rgba和opacity的区别及兼容
主要是作用对象和继承性不同:
- 简述 声明的作⽤。
参考博客:HTML文件里开头的!Doctype有什么作用?
< !Doctype>是文档类型声明,即告诉浏览器当前 HTML 是用什么版本编写的,使得浏览器以W3C的标准解析渲染页面,从而使该页面在所有浏览器中以相同的方式显示。
- 分别列举出三种有继承性和没有继承性的css属性。
参考博客:CSS有哪些属性可以继承?
有继承性:opacity,font-size,color(字体系列和文本系列的很多属性可以被继承)
无继承性:width,background-color,position(盒子模型、定位、背景属性都不能被继承)
- 想要在前端实现动画,如何应对?写出尽可能多的途径。
参考博客:前端实现动画的6种方式详解
在下不才,只遇到过三种,总结如下:
途径一:CSS3 transition过渡动画,不能实现独立的动画,只能在某个标签元素样式或状态改变时进行平滑的动画效果过渡,而不是马上改变。
途径二:CSS3 animation动画,通过对关键帧和循环次数的控制,页面标签元素会根据设定好的样式改变进行平滑过渡。
<html>
<head>
<meta charset="UTF-8">
<title>title>
<style type="text/css">
#box1{
/*width: 100px;*/
/*height: 100px;*/
/*background-color: #bfa;*/
position: absolute;
animation: Ani1 2500ms linear alternate infinite;
/*注意中间用空格隔开,而不是逗号*/
}
#box1:hover{
animation: Ani1 2500ms linear alternate infinite paused;
/*当鼠标放在box上时,停止动画*/
}
@keyframes Ani1{
0%{
width: 100px;
height: 100px;
left: 100px;
top: 50px;
background-color: #bfa;
}
50%{
width: 300px;
height: 300px;
left: 700px;
top: 350px;
background-color: orange;
}
100%{
width: 100px;
height: 100px;
left: 1300px;
top: 50px;
background-color: blue;
}
}
style>
head>
<body>
<div id="box1">
div>
body>
html>
途径三:JS定时器
/*
* 尝试创建一个可以执行简单动画的函数
* 参数:
* obj:要执行动画的对象
* attr:要执行动画的样式,比如:left top width height
* target:执行动画的目标位置
* speed:移动的速度(正数向右移动,负数向左移动)
* callback:回调函数,这个函数将会在动画执行完毕以后执行
*/
function move(obj, attr, target, speed, callback) {
//关闭上一个定时器
clearInterval(obj.timer);
//获取元素目前的位置
var current = parseInt(getStyle(obj, attr));
//判断速度的正负值
//如果从0 向 800移动,则speed为正
//如果从800向0移动,则speed为负
if(current > target) {
//此时速度应为负值
speed = -speed;
}
//开启一个定时器,用来执行动画效果
//向执行动画的对象中添加一个timer属性,用来保存它自己的定时器的标识
obj.timer = setInterval(function() {
//获取box1的原来的left值
var oldValue = parseInt(getStyle(obj, attr));
//在旧值的基础上增加
var newValue = oldValue + speed;
//判断newValue是否大于800
//从800 向 0移动
//向左移动时,需要判断newValue是否小于target
//向右移动时,需要判断newValue是否大于target
if((speed < 0 && newValue < target) || (speed > 0 && newValue > target)) {
newValue = target;
}
//将新值设置给box1
obj.style[attr] = newValue + "px";
//当元素移动到0px时,使其停止执行动画
if(newValue == target) {
//达到目标,关闭定时器
clearInterval(obj.timer);
//动画执行完毕,调用回调函数
callback && callback();
}
}, 30);
}
/*
* 定义一个函数,用来获取指定元素的当前的样式
* 参数:
* obj 要获取样式的元素
* name 要获取的样式名
*/
function getStyle(obj, name) {
if(window.getComputedStyle) {
//正常浏览器的方式,具有getComputedStyle()方法
return getComputedStyle(obj, null)[name];
} else {
//IE8的方式,没有getComputedStyle()方法
return obj.currentStyle[name];
}
}
- BFC是什么?请尽量简要地概括。
b站视频:带你用最简单的方式理解最全面的BFC
前端精选文摘:BFC 神奇背后的原理(没有视频好理解)
BFC的全称为Box Formatting context,即块级格式化上下文。BFC可以看作元素的一种属性,当元素开启BFC时,它可以视作隔离了的独立容器,容器内的元素不会影响到外部的元素。
- 何为 float 流式布局?遇到元素塌陷如何解决?
将float属性设置为left或right,来实现在水平方向上的布局。
如果元素塌陷,两种方式解决:
clear的作用是清除浮动元素对该元素的影响,比如两个块元素本来应该垂直分布,期中A块开启了浮动(假设是left),则B块上移动,开启clear:left后,B不受影响,还在原先的位置。clear的实现原理,是浏览器为B添加了上外边距(不过检查不到),clear:both的作用是清除较大浮动元素的影响。
所以对after开启clear:both后,浏览器会把浮动元素的大小转换为相同大小的上外边距给after,就能撑起父元素了。
完善版.clearfix:
<style>
.clearfix::before,.clearfix::after{
content:'';
display:table;
clear:both;
}
style>
- 请列举你所知道的响应式布局⽅案,以及如何实现响应式。
可参考博客:
前端响应式布局原理与方案(详细,推荐)
响应式布局的实现
一段典型的媒体查询代码:
<style>
@media only screen and (min-width: 500px) and (max-width:700px){
body{
background-color: #bfa;
}
}
style>
参考博客:前端小知识–为什么你写的height:100%不起作用?
<html>
<head>
<meta charset="UTF-8">
<title>title>
<style type="text/css">
html,body
/*注意需要同时设置根元素和body元素*/
{
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#box1{
width: 100%;
height: 100%;
/*background-color: red;*/
display: flex;
justify-content: space-around;
}
#box2{
/*宽度固定,这样视口缩小时,box2间的距离减小*/
width: 100px;
height: 50%;
background-color: #bfa;
}
style>
head>
<body>
<body>
<div id="box1">
<div id="box2">div>
<div id="box2">div>
<div id="box2">div>
<div id="box2">div>
<div id="box2">div>
div>
body>
body>
html>
<html>
<head>
<meta charset="UTF-8">
<title>title>
<style type="text/css">
html{
/*
* 一般在适配移动端时,为了得到一个较好的浏览效果,
* css像素要对应2或3个物理像素,对应的视口大小为750px或1125px
* 此处以750px为例:1vw=7.5px =>1px=0.1333vw =>100px=13.33vw
* 则设置根元素font-size:13.33vw
* (根元素无法设置小于12px的字体,所以无法使用10px=1.333vw)
* 其他元素的大小都用rem设置,1rem=100px
* 这个大小,在全屏的浏览器窗口下,测出的宽度为255/1.25=204px
*/
/*
* 如果想要在分辨率1920x1080电脑的浏览器中得到正确的100px,
* 则设置font-size:13.33*100/204=6.534vw
*/
font-size: 13.33vw;
}
#box1{
width: 1rem;
height: 1rem;
background-color: #bfa;
}
style>
head>
<body>
<div id="box1">div>
body>
html>
<html>
<head>
<meta charset="UTF-8">
<title>title>
<style type="text/css">
#img-wrapper{
/*border: 10px solid red;*/
display: flex;
justify-content: center;
}
img{
display: inline-block;
max-width: 100%;
height: auto;
/*height不设置auto也可,因为auto是默认值*/
}
style>
head>
<body>
<div id="img-wrapper">
<img src="../picture/6.jpg"/>
div>
body>
html>
(补充)如何实现Grid布局?
参考博客:CSS Grid 网格布局教程(阮一峰)(以后看)
(补充)如何实现瀑布流?
参考博客:纯CSS实现瀑布流布局(以后看)
- 读代作画(不做)
- 请补全以下代码,使之呈现下图。(代码中圆圈序号为填空部分,其中有⼀个为⾮必填)
<html>
<head>
<meta charset="UTF-8">
<title>title>
<style type="text/css">
.wrapper{
width: 100%;
background-color: black;
font-size: 0;
border: 20px solid /*①*/ yellow;
padding: 20px;
text-align: center;
vertical-align: /*②*/ middle;
/*上方这句可有可无,②为非必填项*/
}
.big{
height: 200px;
}
.inline{
background-color: white;
font-size: 20px;
margin: 10px;
border: solid 4px blue;
width: 50px;
display: /*③*/ inline-block;
/*④*/vertical-align: middle;
/*text-align应写在父元素中,而vertical-align应写在子元素中*/
}
style>
head>
<body>
<div class="wrapper">
<div class="inline big">这是盒子div>
<div class="inline">这是盒子div>
div>
body>
html>
- 请写代码实现:如何在不影响 let arr = [1,2,3,4,5] 的条件下,为数组添加⼀个新元素6, 并赋值给 arr1 。
一道简单的考察常见数组方法的题。
window.onload = function(){
//最简朴的做法:
let arr = [1,2,3,4,5];
let arr1 = [];
for(i=0;i<arr.length;i++){
arr1[i]=arr[i];
//或arr1.push(arr[i]);
}
arr1[arr.length]=6;
console.log(arr1);
}
window.onload = function(){
let arr = [1,2,3,4,5];
/*以下四行,只要有任意一行即可*/
let arr1 = Array.prototype.slice.apply(arr);
let arr1 = [].slice.call(arr);
let arr1 = arr.slice();
let arr1 = arr.slice(0,arr.length);
arr1.push(6);
console.log(arr1);
}
- 请在合适的⾏尾写出输出结果,并注释原因。
抄代码的时候把代码抄进window.onload了,引发了灾难,参考博客:
window.onload 函数引发的血案
如果不加var,即便在window.onload之内声明,变量都为顶层(全局)变量;而var声明的就成了局部变量,所以window.a才为undefined。
第一版代码:
window.onload = function(){
function foo(){
console.log(this.a);
}
var a = 1;
//如果去掉var,输出结果会变成2 1 1 undefined 2
const obj = {
a:2,
foo:foo
}
obj.foo();//2
foo();//undefined
console.log(window.a);//undefined
const c = new foo();//undefined
/*
*注意:new的时候把原函数执行了一次
*此时this.a就是c.a,由于c的a未定义,
*沿着原型链找回去,foo的a也未定义,所以输出undefined
*/
const d = Object.create(obj);
//使用create方法,d是obj的实例对象
d.foo();//2
//d的a未定义,但沿原型链可以找到obj.a=2
}
原题代码:
function foo(){
console.log(this.a);
}
var a = 1;
const obj = {
a:2,
foo:foo
}
obj.foo();
//2,foo作为obj的方法调用时,this指向obj
foo();
//1,this指向window
const c = new foo();//undefined
/*
*注意:new的时候把原函数执行了一次
*此时this.a就是c.a,由于c的a未定义,
*沿着原型链找回去,foo也是一个对象,foo的a未定义,
*所以输出undefined
*/
const d = Object.create(obj);
//使用create方法,d是obj的实例对象
d.foo();//2
//d的a未定义,但沿原型链可以找到obj.a=2
- 写出输出结果并说明原因。
参考回答:js变量与函数同名
有如下原则:
var a = 10;
var a;
function a(){
console.log('aoe');
}
console.log(a);//10
/*
以上代码等价于:
function a(){
console.log('aoe');
}
var a;
var a;(无效)
a = 10;
console.log(a);//10
//如果没有a=10,则输出结果为函数
*/
- 下⾯两个 for 语句的结果有何不同?为什么?
for(var i=0;i<3;i++){
setTimeout(()=>{
console.log(i);
},0)
}// 3 3 3
// var声明的i为全局变量,循环结束执行定时器时,i的值已经变为3
for(let i=0;i<3;i++){
setTimeout(()=>{
console.log(i);
},0)
}// 0 1 2
// let声明的i存在块级作用域,每一轮给计时器绑定一个不同的i
Node.js不会,做不了
node.js 是什么?如何判断⾃⼰是否处于 node 环境中?
node.js是运行在服务器端的javascript,它不是一种新的语言,而是js的一种运行环境
由于node中不包括DOM,通过判断全局对象是否为window,如果不为window,则当前脚本运行在node.js环境中
this === window ? console.log('browser') : console.log('node');
请按照⾃⼰的理解,描述 node.js 的运⾏模型。
参考博客:
Node.js 运行机制:Event Loop
事件循环模型 Event Loop
:
事件循环
。在事件循环里的每一个阶段都查看该阶段的任务队列是否为空,如果不为空则尝试同步执行(以先进先出顺序一个一个执行)所有队列里的任务直到队列为空。如果回调队列为空且没有需要等待完成的异步操作,这个 Node.js 进程就结束了。在 node.js 中, module.export 与 exports 有何区别?
写出以下代码在 node 环境中的输出。
参考博客:setTimeout和setImmediate到底谁先执行,本文让你彻底理解Event Loop(强推)
这题和原先一道浏览器下的js题目很像,多考了setImmediate和setTimeout的先后顺序问题
'use strict'
var maple = {
baz: 3,
};
var foo = {
baz: 4,
bar: function() {
console.log(this);
for(var i = 0; i < maple.baz; i++) {
setImmediate(function() {
console.log(i);
});
}
for(let i = 0; i < this.baz; i++){
setTimeout(function() {
console.log(i);
})
}
}
};
foo.bar.bind(foo).call(maple);
输出结果是:
{ baz: 4, bar: [Function: bar] }
3
3
3
0
1
2
3
解析:
node.js的Event Loop是分阶段的:timers、pending callbacks、idle/prepare、poll、check、close callbacks,其中setTimeout在timers阶段,而setImmediate在check阶段。在同步任务执行完成,开始执行异步任务的时候,由于setImmediate在上,且pending callbacks、idle/prepare、poll等队列都是空的,直接到check阶段,由主线程执行setImmediate中的代码,再到下一个事件循环,到timers阶段,由主线程执行setTimeout中的代码。
如果把setImmediate和setTimeout反过来写,则可能先进行前者,也可能先执行后者。因为会直接到timers阶段,只要此时时间到了1ms,就执行setTimeout(没到1ms就到下一个循环的timers阶段),然后到check阶段,执行setImmediate。
做不了 我觉得自己还可以抢救一下
阅读理解:请先通读⽂档:https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/,回答以下问题:
- 为什么下⾯这段代码中的 setImmediate ⼀定先执⾏?
const fs = require('fs');
fs.readFile(__filename, () => {
setTimeout(() => {
console.log('timeout');
});
setImmediate(() => {
console.log('immediate');
});
});
node.js的Event Loop是分阶段的:timers、pending callbacks、idle/prepare、poll、check、close callbacks,其中setTimeout在timers阶段,而setImmediate在check阶段。在同步任务执行完成,开始执行异步任务的时候,由于代码都写在fs.readFile的函数中,readFile属于I/O操作,会直接跳到poll阶段,poll结束后到了check阶段,执行setImmediate中的代码,然后到下一次循环的timers阶段,执行setTimeout中的代码
- 上⾯⼀段代码中, setTimeout 存在第⼆个参数,这个参数默认为多少?
默认是0,但node.js限制setTimeout时间的最小值为1ms,所以会被强制改为1ms
- process.nextTick() 与 setImmediate() 有何区别?
SetImmediate()属于check阶段,而process.nextTick是一个特殊的异步API,他不属于任何的Event Loop阶段。
Node在遇到这个API时,Event Loop根本就不会继续进行,会马上停下来执行process.nextTick(),这个执行完后才会继续Event Loop。
- 写出下⾯代码的执⾏结果并说明理由。
new Promise((resolve) => {
setImmediate(() => {
console.log('setImmediate')
})
resolve()
}).then(() => {
process.nextTick(() => {
console.log('nextTick')
setImmediate(() => console.log('nextImmediate'))
})
console.log('promise.then')
})
一定要记住,同步代码最先执行,console.log(‘setImmediate’)比console.log(‘nextImmediate’)先进入任务队列
2.4 刷题暂告一段落,感到H5/CSS/JS有了一定提升。
继续学习ES6和Git,练习做网页吧,Node和计网不着急。
3.10 从现在开始,补上一部分以前没做的题
参考博客:JavaScript数组去重
这段代码性能或许不好,因为我拿它对下一段代码中的原始数组去重时,浏览器说内存不足,无法打开网页
<!DOCTYPE html>
/*
* 1.创建一个新数组,把原数组中的第一个元素插入到新数组中
* 2.遍历原数组中的每一个元素分别和新数组中的每一个元素进行比较
*/
//原数组
var arr = [8,11,20,5,20,8,0,2,4,0,8];
// 新数组
var t = [];//var t = [8,11];
t[0] = arr[0];
//arr中的每个元素
for(var i=0;i<arr.length;i++){
//t中的每个元素
for(var k = 0;k<t.length;k++){
//当原数组中的值和新数组中的值相同的时候,就没有必要再继续比较了,跳出内循环
if(t[k] == arr[i]){
break;
}
//拿原数组中的某个元素比较到新数组中的最后一个元素还没有重复
if(k == t.length-1){
//将数据插入新数组
t.push(arr[i]);
}
}
}
console.log(t);
function unique(arr){
for(var i=0; i<arr.length; i++){
for(var j=i+1; j<arr.length; j++){
if(arr[i]==arr[j]){
//第一个等同于第二个,splice方法删除第二个
arr.splice(j,1);
j--;
}
}
}
return arr;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{
},{
}];
console.log(unique(arr))
//[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}]
NaN和{}没有去重,两个null直接消失了
function unique(arr) {
if (!Array.isArray(arr)) {
console.log('type error!')
return
}
var array = [];
for (var i = 0; i < arr.length; i++) {
if (array.indexOf(arr[i]) === -1) {
//indexOf()方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。
array.push(arr[i])
}
}
return array;
}
var arr = [1, 1, 'true', 'true', true, true, 15, 15, false, false, undefined, undefined, null, null, NaN, NaN, 'NaN', 0, 0, 'a', 'a', {
}, {
}];
console.log(unique(arr))
// [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}]
NaN、{}没有去重
function unique(arr) {
if (!Array.isArray(arr)) {
console.log('type error!')
return;
}
arr = arr.sort()
var arrry= [arr[0]];
for (var i = 1; i < arr.length; i++) {
//排列好后,只需要一层循环就可以了
if (arr[i] !== arr[i-1]) {
arrry.push(arr[i]);
}
}
return arrry;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{
},{
}];
console.log(unique(arr))
// [0, 1, 15, "NaN", NaN, NaN, {…}, {…}, "a", false, null, true, "true", undefined]
NaN、{}没有去重
function unique(arr) {
return arr.filter(function(item, index, arr) {
//当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
return arr.indexOf(item, 0) === index;
});
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{
},{
}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, "NaN", 0, "a", {…}, {…}]
NaN不见了,{}没有去重
因为object的key是string类型的,无论你传入什么,他都会解析成字符串(symbol和Map等新特性除外),所以这就导致了数字1和字符串1,他在object中的key是相同的,而你应该不想把他们当成相同的数据给去除掉。所以这里使用了typeof来简单判断了下类型。
不用觉得typeof item + item很奇怪,只要明白,每个元素对应的 typeof item + item 都是不同的,只要它能起到标识每一个元素的作用,那么就足够了
function unique(arr) {
var obj = {
};
return arr.filter(function(item, index, arr){
return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
})
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{
},{
}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}] //所有的都去重了
全部实现去重
let arr = [1,2,3,4,5,4,3,2,1];
let result = [...new Set(arr)];
console.log(result);
//也可以这样写:
function unique (arr) {
return Array.from(new Set(arr))
//from()方法的作用是生成数组
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{
},{
}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]
//最简化的写法:
[...new Set(arr)]
缺陷:无法去除{}空对象