一、HTML/CSS
1、什么是盒子模型?
一个空间由几部分组成:边框、内边距、外边距、内容。
IE 盒子模型:包括 margin、border、padding、content, content 部分包含了 border 和 pading
标准 W3C 盒子模型:包括 margin、border、padding、content;content 部分不包含其他
2、行内元素有哪些 ?块级元素有哪些?空元素有哪些?
行内元素:a、b、span、img、input、strong、select、label、em、button、textarea
块级元素:div、ul、li、p、h1、h2、h3、h4、h5、h6
空元素:input、img、br、hr、meta、link
3、HTML5新特性,语义化
简洁的DOCTYPE:<!DOCTYPE html>
简单易记的编码类型:<meta charset=”utf-8″ />
脚本和链接无需type:
<link rel="stylesheet" href="path/to/stylesheet.css" />
<script src="path/to/script.js"></script>
语义化新增标签:<article>、<section>、<aside>、<hgroup>、 <header>,<footer>、<nav>、<time>、<mark>、<figure> 和<figcaption>
4、什么是优雅降级和渐进增强?
优雅降级:开始构建完整的项目,后期针对低版本浏览器进行兼容;
渐进增强:针对低版本浏览器构建页面,保证最基本功能,然后针对高级浏览器进行效果、交互等改进和追加功能达到更好的体验。
5、 display属性和 visibility属性的区别?
Display:inlin-block像内联元素一样显示,none不显示不占空间,block像块级元素一样显示;
Visibility:hidden;仅仅是视觉上透明不显示,空间位置占据
6、CSS中link 和@import的区别是?
(1) link属于HTML标签,而@import是CSS提供的;
(2) 页面被加载的时,link会同时被加载,而@import被引用的CSS会等到引用它的CSS文件被加载完再加载;
(3) import只在IE5以上才能识别,而link是HTML标签,无兼容问题;
(4) link方式的样式的权重 高于@import的权重.
7、box-sizing属性主要用来控制元素的盒模型的解析模式。默认值是content-box。
content-box:让元素维持W3C的标准盒模型。元素的宽度/高度由border + padding + content的宽度/高度决定,设置width/height属性指的是content部分的宽/高
border-box:让元素维持IE传统盒模型(IE6以下版本和IE6~7的怪异模式)。设置width/height属性指的是border + padding + content
8、CSS3新特性;
增加了新的选择器:属性选择器([attribute^=value]、[attribute$=value]、[attribute*=value])
伪类选择器:动作伪类、nth选择器等;
Transition(过渡),
Transform(动画2D、3D)该属性允许我们对元素进行旋转、缩放、移动或倾斜等操作
Animation(动画)
渐变:linear-gradient(线性渐变)和radial-gradient(径向渐变)
9、你做的页面在哪些流览器测试过?这些浏览器的内核分别是什么?
Ie(trident) 火狐(Gecko) 谷歌(webkit) opear(Presto)
10、.前端页面有哪三层构成,分别是什么?作用是什么?
结构层 Html 表示层 CSS 行为层 js
11、写出几种IE6 BUG的解决方法
双边距BUG float引起的 使用display
像素问题 使用float引起的 使用dislpay:inline -3px
超链接hover 点击后失效 使用正确的书写顺序 link visited hover active
Ie z-index问题 给父级添加position:relative
Png 透明 使用js代码 改
Min-height 最小高度 !Important 解决’
select 在ie6下遮盖 使用iframe嵌套
为什么没有办法定义1px左右的宽度容器(IE6默认的行高造成的,使用over:hidden,zoom:0.08 line-height:1px)
12、css元素的垂直居中
<1>divParent{position:relative}
divChild{
400px;
height:400px;
position:absolute;
top:50%;
left:50%;
margin-left:-200px;
margin-top:-200px;
}
<2>divBox{
display:table-cell;
Vertical:middle;
Text-align:center;
}
<3>divParent{
Width:800px;
Height:800px;
Display:flex;
Justify-content:center;
Align-items:center;
}
<4>divParent{
Width:800px;
Height:800px;
Position:relative;
}
divChild{
Width:200px;
Height:200px;
Position:absolute;
Margin:auto;
Top:0;
Bottom:0;
Left:0;
Right:0;
}
13、右边固定宽度,左边自适应
第一种:
<style>
body{
display: flex;
}
.left{
height: 200px;
flex: 1;
}
.right{
background-color: red;
height: 200px;
100px;
}
</style>
<body>
<div class="left"></div>
<div class="right"></div>
</body>
第二种:
<style>
div {
height: 200px;
}
.left {
float: right;
200px;
background-color: rebeccapurple;
}
.right {
margin-right: 200px;
background-color: red;
}
</style>
<body>
<div class="left"></div>
<div class="right"></div>
</body>
14、关于清除浮动的四种方法
overflow:hidden; .clear{clear:both;};父级div定义 height
15、flex弹性布局?(多次)
Flex是Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。
注:设为 Flex 布局以后,子元素的float、clear和vertical-align属性将失效。
分为容器和容器成员:容器的属性(6个)
flex-direction:决定主轴方向(水平左(默认)、水平右、垂直上、垂直下)
flex-wrap:决定换行方式(不换行、第一行在上、第二行在上)
flex-flow
justify-content:项目在主轴上的对齐方式
align-items
align-content
14、rem布局原理
原理是,先按定高宽设计出来页面,然后转换为rem单位,配合js查询屏幕大小来改变html的font-size,最终做出所谓的完美自适应。
二、javascript
1、js的基本类型有哪些?引用类型有哪些?null和undefined的区别。
基本类型就是Undefined、Null、Boolean、Number、String;
引用类型是object;
undefined表示变量声明但未初始化时的值,
null表示准备用来保存对象,还没有真正保存对象的值。从逻辑角度看,null值表示一个空对象指针。
2、如何判断一个变量是Array类型?如何判断一个变量是Number类型?(都不止一种)
Object.prototype.toString
function isArrayFn (o) {
return Object.prototype.toString.call(o) .slice(8,-1)=== '[object Array]';
}
var arr = [1,2,3,1];
alert(isArrayFn(arr));// true
Array.isArray()
最佳:
var arr = [1,2,3,1];
var arr2 = [{ abac : 1, abc : 2 }];
function isArrayFn(value){
if (typeof Array.isArray === "function") {
return Array.isArray(value);
}else{
return Object.prototype.toString.call(value) === "[object Array]";
}
}
alert(isArrayFn(arr));// true
alert(isArrayFn(arr2));// true
3、DOM操作——怎样添加、移除、移动、复制、创建和查找节点。
(1)创建新节点
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
(2)添加、移除、替换、插入
appendChild()
removeChild()
replaceChild()
insertBefore() //并没有insertAfter()
(3)查找
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值(IE容错能力较强,
会得到一个数组,其中包括id等于name值的)
getElementById() //通过元素Id,唯一性
4、创建ajax的过程
(1)创建`XMLHttpRequest`对象,也就是创建一个异步调用对象.
(2)创建一个新的`HTTP`请求,并指定该`HTTP`请求的方法、`URL`及验证信息.
(3)设置响应`HTTP`请求状态变化的函数.
(4)发送`HTTP`请求.
(5)获取异步调用返回的数据.
(6)使用JavaScript和DOM实现局部刷新.
function loadShow(){
Var xmlHttp;
If(window.MXLHTTPRequest){
xmlHttp=new XMLHTTPRequest();
}else{
xmlHttp=new ActiveXObject(“Microsoft.XMLHTTP”)
};
xmlHttp.onreadystatechange=function(){
If(xmlHttp.readyState===4&&xmlHttp.status===200){
Document.getElementById(“ID”).innerHTML=xmlHttp.responseText
}
};
xmlHttp.open(‘GET’,’demo.php’,true);
xmlHttp.send()
}
$.ajax({
Url:”请求地址”,
dataType:”xml jsonp json text html script”,//数据类型
Anysnc:”true”,//是否异步
Data:{‘’:’’},
Type:”GET”,//请求格式
Beforesendfunction(){},
Success:function(){},
Completefunction(){},
Error:function(){}
})
5、ajax的缺点
(1)ajax不支持浏览器back按钮。
(2)安全问题 AJAX暴露了与服务器交互的细节。
(3)对搜索引擎的支持比较弱。
(4)破坏了程序的异常机制。
(5)不容易调试。
6、GET和POST的区别,何时使用POST?
GET:一般用于信息获取,使用URL传递参数,对所发送信息的数量也有限制,一般在2000个字符
POST:一般用于修改服务器上的资源,对所发送的信息没有限制。
GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值,也就是说Get是通过地址栏来传值,而Post是通过提交表单来传值。
然而,在以下情况中,请使用 POST 请求:
无法使用缓存文件(更新服务器上的文件或数据库)
向服务器发送大量数据(POST 没有数据量限制)
发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
7、HTTP状态码:
100 Continue 继续,一般在发送post请求时,已发送了http header之后服务端将返回此信息,表示确认,之后发送具体参数信息
200 OK 正常返回信息
201 Created 请求成功并且服务器创建了新的资源
202 Accepted 服务器已接受请求,但尚未处理
301 Moved Permanently 请求的网页已永久移动到新位置。
302 Found 临时性重定向。
303 See Other 临时性重定向,且总是使用 GET 请求新的 URI。
304 Not Modified 自从上次请求后,请求的网页未修改过。
400 Bad Request 服务器无法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求。
401 Unauthorized 请求未授权。
403 Forbidden 禁止访问。
404 Not Found 找不到如何与 URI 相匹配的资源。
500 Internal Server Error 最常见的服务器端错误。
503 Service Unavailable 服务器端暂时无法处理请求(可能是过载或维护)。
8、javascript继承的优缺点:
(1)原型链继承:字面量重写原型会中断关系,子类型无法给超类型传参
(2)借用构造函数继承:可以传参,但没有原型,无法复用
(3)组合继承(原型链和构造函数)
原型链继承:(利用原型让一个引用类型继承另外一个引用类型的属性和方法)
function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function() {
return this.property;
}
function subType() {
this.property = false;
}
//继承了SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function (){
return this.property;
}
var instance = new SubType();
console.log(instance.getSuperValue());//true
借用构造函数:(在子类型构造函数的内部调用超类构造函数,通过使用call()和apply()方法可以在新创建的对象上执行构造函数)
function SuperType() {
this.colors = ["red","blue","green"];
}
function SubType() {
SuperType.call(this);//继承了SuperType
}
var instance1 = new SubType();
instance1.colors.push("black");
console.log(instance1.colors);//"red","blue","green","black"
var instance2 = new SubType();
console.log(instance2.colors);//"red","blue","green"
组合继承:(将原型链和借用构造函数的技术组合在一块,从而发挥两者之长的一种继承模式)
function SuperType(name) {
this.name = name;
this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function() {
console.log(this.name);
}
function SubType(name, age) {
SuperType.call(this,name);//继承属性
this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
Subtype.prototype.constructor = Subtype;
Subtype.prototype.sayAge = function() {
console.log(this.age);
}
var instance1 = new SubType("EvanChen",18);
instance1.colors.push("black");
consol.log(instance1.colors);//"red","blue","green","black"
instance1.sayName();//"EvanChen"
instance1.sayAge();//18
var instance2 = new SubType("EvanChen666",20);
console.log(instance2.colors);//"red","blue","green"
instance2.sayName();//"EvanChen666"
instance2.sayAge();//20
原型式继承:(借助原型可以基于已有的对象创建新对象,同时还不必须因此创建自定义的类型)
var person = {
name:"EvanChen",
friends:["Shelby","Court","Van"];
};
var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
console.log(person.friends);//"Shelby","Court","Van","Rob","Barbie"
寄生式继承:(创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真正是它做了所有工作一样返回对象)
function createAnother(original) {
var clone = object(original);
clone.sayHi = function () {
alert("hi");
};
return clone;
}
var person = {
name:"EvanChen",
friends:["Shelby","Court","Van"];
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi();///"hi"
寄生组合式继承(通过借用函数来继承属性,通过原型链的混成形式来继承方法)
function SuperType(name){
this.name = name;
this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function (){
alert(this.name);
};
function SubType(name,age){
SuperType.call(this,name);
this.age = age;
}
inheritProperty(SubType,SuperType);
SubType.prototype.sayAge = function() {
alert(this.age);
}
9、简述一次完整的HTTP请求是怎样一个过程?
(1)域名解析:解析域名为对应的ip地址(首先浏览器自身DNS缓存,没有则会针对系统DNS缓存,再没有则尝试读取hosts文件)
(2)发起tcp3次握手(获得ip地址后,浏览器会以一个随机端口向服务器的web程序发起tcp请求链接)
(3)建立tcp连接后发起http请求
(4)服务器端响应HTTp请求,浏览器得到html代码
(5)浏览器解析HTML代码,渲染呈现给用户
10、把接收的json数据转换成json字符
obj.toJSONString(); //将JSON对象转化为JSON字符
JSON.stringify(obj); //将JSON对象转化为JSON字符
11、创建对象的多种方式
第一种:用Object构造函数
var a = new Object();
var b = new Object();
第二种:对象字面量的方式
var a = {};
a.name = 'li';
a.age = 21;
12、new 一个对象具体做了什么
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
第一行,我们创建了一个空对象obj
第二行,我们将这个空对象的__proto__成员指向了Base函数对象prototype成员对象
第三行,我们将Base函数对象的this指针替换成obj,然后再调用Base函数,于是我们就给obj对象赋值了一个id成员变量,这个成员变量的值是”base”,关于call函数的用法。
13、javascript闭包
function f1(){
var n=999;
function f2(){
alert(n); // 999
}
}
概念:内部受保护的函数就是闭包;(闭包就是能够读取其他函数内部变量的函数。)
由于在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成“定义在一个函数内部的函数”。所以,在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
闭包的用途:一个是前面提到的可以读取函数内部的变量,二是让这些变量的值始终保持在内存中,不会在f1调用后被自动清除。
使用闭包的注意点
(1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
(2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
14、变量提升变量提升即将变量声明提升到它所在作用域的最开始的部分。
console.log(global); // undefined
var global = 'global';
console.log(global); // global
function fn () {
console.log(a); // undefined
var a = 'aaa';
console.log(a); // aaa
}
fn();
本质代码如下:
var global; // 变量提升,全局作用域范围内,此时只是声明,并没有赋值
console.log(global); // undefined
global = 'global'; // 此时才赋值
console.log(global); // 打印出global
function fn () {
var a; // 变量提升,函数作用域范围内
console.log(a);
a = 'aaa';
console.log(a);
}
fn();
15、函数提升
js中创建函数有两种方式:函数声明式和函数字面量式。只有函数声明才存在函数提升!
console.log(f1); // function f1() {}
console.log(f2); // undefined
function f1() {}
var f2 = function() {}
执行如下:
function f1() {} // 函数提升,整个代码块提升到文件的最开始<br> console.log(f1);
console.log(f2);
var f2 = function() {}
16、常用的字符串函数
concat() – 将两个或多个字符的文本组合起来,返回一个新的字符串。
indexOf() – 返回字符串中一个子串第一处出现的索引。如果没有匹配项,返回 -1 。
charAt() – 返回指定位置的字符。
lastIndexOf() – 返回字符串中一个子串最后一处出现的索引,如果没有匹配项,返回 -1 。
match() – 检查一个字符串是否匹配一个正则表达式。
substr() 函数 -- 返回从string的startPos位置,长度为length的字符串
substring() – 返回字符串的一个子串。传入参数是起始位置和结束位置。
slice() – 提取字符串的一部分,并返回一个新字符串。
replace() – 用来查找匹配一个正则表达式的字符串,然后使用新字符串代替匹配的字符串。
search() – 执行一个正则表达式匹配查找。如果查找成功,返回字符串中匹配的索引值。否则返回 -1 。
split() – 通过将字符串划分成子串,将一个字符串做成一个字符串数组。
length – 返回字符串的长度,所谓字符串的长度是指其包含的字符的个数。
toLowerCase() – 将整个字符串转成小写字母。
toUpperCase() – 将整个字符串转成大写字母。
17、常用的数组函数
concat() 连接两个或更多的数组,并返回结果。
join() 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。
pop() 删除并返回数组的最后一个元素。
shift() 删除并返回数组的第一个元素
push() 向数组的末尾添加一个或更多元素,并返回新的长度。
unshift() 向数组的开头添加一个或更多元素,并返回新的长度。
reverse() 颠倒数组中元素的顺序。
slice() 从某个已有的数组返回选定的元素
sort() 对数组的元素进行排序
splice() 删除元素,并向数组添加新元素。
toSource() 返回该对象的源代码。
toString() 把数组转换为字符串,并返回结果。
toLocaleString() 把数组转换为本地数组,并返回结果。
valueOf() 返回数组对象的原始值
18、jQuery的事件委托方法bind 、live、delegate、on之间有什么区别?
<1>、bind 【jQuery 1.3之前】
定义和用法:主要用于给选择到的元素上绑定特定事件类型的监听函数;
语法:bind(type,[data],function(eventObject));
特点:
(1)、适用于页面元素静态绑定。只能给调用它的时候已经存在的元素绑定事件,不能给未来新增的元素绑定事件。
(2)、当页面加载完的时候,你才可以进行bind(),所以可能产生效率问题。
实例如下:$( "#members li a" ).bind( "click", function( e ) {} );
<2>、live 【jQuery 1.3之后】
定义和用法:主要用于给选择到的元素上绑定特定事件类型的监听函数;
语法:live(type, [data], fn);
特点:
(1)、live方法并没有将监听器绑定到自己(this)身上,而是绑定到了this.context上了。
(2)、live正是利用了事件委托机制来完成事件的监听处理,把节点的处理委托给了document,新添加的元素不必再绑定一次监听器。
(3)、使用live()方法但却只能放在直接选择的元素后面,不能在层级比较深,连缀的DOM遍历方法后面使用,即$(“ul”").live...可以,但$("body").find("ul").live...不行;
实例如下:$( document ).on( "click", "#members li a", function( e ) {} );
<3>、delegate 【jQuery 1.4.2中引入】
定义和用法:将监听事件绑定在就近的父级元素上
语法:delegate(selector,type,[data],fn)
特点:
(1)、选择就近的父级元素,因为事件可以更快的冒泡上去,能够在第一时间进行处理。
(2)、更精确的小范围使用事件代理,性能优于.live()。可以用在动态添加的元素上。
实例如下:
$("#info_table").delegate("td","click",function(){/*显示更多信息*/});
$("table").find("#info").delegate("td","click",function(){/*显示更多信息*/});
<4>、on 【1.7版本整合了之前的三种方式的新事件绑定机制】
定义和用法:将监听事件绑定到指定元素上。
语法:on(type,[selector],[data],fn)
实例如下:$("#info_table").on("click","td",function(){/*显示更多信息*/});参数的位置写法与delegate不一样。
说明:on方法是当前JQuery推荐使用的事件绑定方法,附加只运行一次就删除函数的方法是one()。
.bind(), .live(), .delegate(),.on()分别对应的相反事件为:.unbind(),.die(), .undelegate(),.off()
19、$(document).ready()方法和window.onload有什么区别?
(1)、window.onload方法是在网页中所有的元素(包括元素的所有关联文件)完全加载到浏览器后才执行的。
(2)、$(document).ready() 方法可以在DOM载入就绪时就对其进行操纵,并调用执行绑定的函数。
20、tap和click事件的区别?
两者都会在点击时触发,但在web移动端click会有200-300ms的延时,所以要用tap代替click作为点击事件,singleTap和doubleTap分别作为单次点击和双击,但是使用tap会带来点透事件(事件穿透)。
21、什么是跨域?跨域请求资源的方法有哪些?
//什么是跨域?
由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。存在跨域的情况:
网络协议不同,如http协议访问https协议。
端口不同,如80端口访问8080端口。
域名不同,如qianduanblog.com访问baidu.com。
子域名不同,如abc.qianduanblog.com访问def.qianduanblog.com。
域名和域名对应ip,如www.a.com访问20.205.28.90.
//跨域请求资源的方法:
(1)、porxy代理
定义和用法:proxy代理用于将请求发送给后台服务器,通过服务器来发送请求,然后将请求的结果传递给前端。
实现方法:通过nginx代理;
注意点:1、如果你代理的是https协议的请求,那么你的proxy首先需要信任该证书(尤其是自定义证书)或者忽略证书检查,否则你的请求无法成功。
(2)、CORS 【Cross-Origin Resource Sharing】
定义和用法:是现代浏览器支持跨域资源请求的一种最常用的方式。
使用方法:一般需要后端人员在处理请求数据的时候,添加允许跨域的相关操作。如下:
res.writeHead(200, {
"Content-Type": "text/html; charset=UTF-8",
"Access-Control-Allow-Origin":'http://localhost',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'X-Requested-With, Content-Type'
});
(3)、jsonp
定义和用法:通过动态插入一个script标签。浏览器对script的资源引用没有同源限制,同时资源加载到页面后会立即执行(没有阻塞的情况下)。
特点:通过情况下,通过动态创建script来读取他域的动态资源,获取的数据一般为json格式。
实例如下:
<script>
function testjsonp(data) {
console.log(data.name); // 获取返回的结果 }</script>
<script>
var _script = document.createElement('script');
_script.type = "text/javascript";
_script.src = "http://localhost:8888/jsonp?callback=testjsonp";
document.head.appendChild(_script);</script>
缺点:
1、这种方式无法发送post请求(这里)
2、另外要确定jsonp的请求是否失败并不容易,大多数框架的实现都是结合超时时间来判定。
22、判断一个字符串中出现次数最多的字符,统计这个次数
var str = 'asdfssaaasasasasaa';var json = {};for (var i = 0; i < str.length; i++) {
if(!json[str.charAt(i)]){
json[str.charAt(i)] = 1;
}else{
json[str.charAt(i)]++;
}
};var iMax = 0;var iIndex = '';for(var i in json){
if(json[i]>iMax){
iMax = json[i];
iIndex = i;
}
}
console.log('出现次数最多的是:'+iIndex+'出现'+iMax+'次');
23、如何获取浏览器URL查询字符串中的参数
function showWindowHref(){
var sHref = window.location.href;
var args = sHref.split('?');
if(args[0] == sHref){
return "";
}
var arr = args[1].split('&');
var obj = {};
for(var i = 0;i< arr.length;i++){
var arg = arr[i].split('=');
obj[arg[0]] = arg[1];
}
return obj;
}
var href = showWindowHref(); // obj
console.log(href['name']); // xiaoming
24、数组去重的常用方法
//遍历数组法
Function unique1(array){
Var str1=[];
For(var i=0;i<array.length;i++){
If(str1.indexOf(array[i])==-1){
Str1.push(array[i])
}
}
Return str1;
}
//先排序相邻去除法
Function unique2(array){
Array.sort();
Var str2=[array[0]];
For(var i=0;i<array.length;i++){
If(array[i]!==str2[str2.length-1]){
Str2.push(array[i])
}
}
Return str2;
}
//对象键值对法
Function unique3(array){
Var obj={},str3=[];
For(var i=0;i<array.length;i++){
If(!obj[array[i]]){
Str3.push(array[i]);
Obj[array[i]]=1;
}
}
Return str3;
}
25、克隆函数
Function clone(obj){
Var o;
Switch(typeOf obj){
Case “undefined”:
Break;
Case “string”:o=obj+””;
Break;
Case “number”:o=obj-0;
Break;
Case “boolean”:o=obj;
Break;
Case “object”:
If(obj===null){
o=null;
}else {
If(Object.prototype.toString.call(obj).slice(8,-1)===”Array”){
O=[];
For(var i=0;i<obj.length;i++){
O.push(clone(obj[i]))
}
}else{
O={};
For(var key in obj){
O[key]=clone(obj[key])
}
}
}
Break;
Default :o=obj;
Break;
}
Return o;
}
26、排序算法
//1、冒泡排序
function subSort(arr1){
for(var i=0;i<arr1.length;i++){
for(var j=0;j<arr1.length-1-i;j++){
if(arr1[j]>arr1[j+1]){//相邻元素对比
var temp=arr1[j+1];
arr1[j+1]=arr1[j];
arr1[j]=temp;
}
}
}
return arr1;
}
var arr1=[3,5,9,8,11,55,22,44,12,23]
console.log(subSort(arr1))
//2.选择排序
function selectionSort(arr2){
var temp,minIndex
for(var i=0;i<arr2.length-1;i++){
minIndex=i;
for(var j=i+1;j<arr2.length;j++){
if(arr2[j]<arr2[minIndex]){
minIndex=j
}
}
temp=arr2[i]
arr2[i]=arr2[minIndex]
arr2[minIndex]=temp
}
return arr2
}
var arr2=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(selectionSort(arr2));
//3.插入排序
function insertionSort(array) {
for (var i = 1; i < array.length; i++) {
var key = array[i];
var j = i - 1;
while ( array[j] > key) {
array[j + 1] = array[j];
j--;
}
array[j + 1] = key;
}
return array;
}
var arr3=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(insertionSort(arr3));
27、JavaScript两个变量交换值的实现方法
//1.普通做法
var a=1,b=2;
var temp;
temp=a
a=b
b=temp
通过变量temp作为中间量,将两个变量值进行交换
//2.算数运算
var a = 1,b = 2;
a = a + b; // a = 3, b = 2
b = a - b; // a = 3, b = 1
a = a - b;// a = 2, b = 1
//3.ES6解构
let a = 1,b = 2;
[a, b] = [b, a];
28、数字转成大写:
function intToChinese ( str ) {
str = str+'';
var len = str.length-1;
var idxs = ['','十','百','千','万','十','百','千','亿','十','百','千','万','十','百','千','亿'];
var num = ['零','壹','贰','叁','肆','伍','陆','柒','捌','玖'];
return str.replace(/([1-9]|0+)/g,function( $, $1, idx, full) {
var pos = 0;
if( $1[0] != '0' ){
pos = len-idx;
if( idx == 0 && $1[0] == 1 && idxs[len-idx] == '十'){
return idxs[len-idx];
}
return num[$1[0]] + idxs[len-idx];
} else {
var left = len - idx;
var right = len - idx + $1.length;
if( Math.floor(right/4) - Math.floor(left/4) > 0 ){
pos = left - left%4;
}
if( pos ){
return idxs[pos] + num[$1[0]];
} else if( idx + $1.length >= len ){
return '';
}else {
return num[$1[0]]
}
}
});
}
29、回文的判断?
function isPalindrome(line) {
line += "";
for(var i=0,j=line.length-1;i<j;i++,j--){
if(line.charAt(i) !== line.charAt(j)){
return false;
}
}
return true;
}
30、判断邮箱
RegExp(/^([a-zA-Z0-9._-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/)
31、驼峰命名与连字符命名的转换
驼峰转连字符:
function getKebabCase ( str ) {
var arr = str.split('');
str = arr.map(function ( item ){
if( item.toUpperCase() === item ){
return '-' + item.toLowerCase();
}else{
return item; }
}).join( '' );
return str;
}
console.log( getKebabCase( 'getElementById' ) ); //get-element-by-id
function getKebabCase( str ) {
return str.replace( /[A-Z]/g, function( i ) {
return '-' + i.toLowerCase();
})
}
console.log( getKebabCase( 'getElementById' ) ); //get-element-by-id
转驼峰
function getCamelCase( str ) {
var arr = str.split( '-' );
return arr.map( function( item, index ) {
if( index === 0 ){
return item;
}else{
return item.charAt(0).toUpperCase() + item.slice( 1 ); }
}).join('');
}
console.log( getCamelCase( 'get-element-by-id' ) ); //getElementById
function getCamelCase( str ) {
return str.replace( /-([a-z])/g,
function( all, i ){
return i.toUpperCase();
} )
}
console.log( getCamelCase( 'get-element-by-id' ) ); //getElementById
32、js去掉前后字符
function trim(str){
return str.replace(/(^s*)|(s*$)/g, "");
}
33、第1个人10,第2个比第1个人大2岁,依次递推,计算出第8个人多大 (递归)
function add(n){
var num=10;
for(var i=1;i<n;i++){
num=num+2;
}
return num;
}
console.log(add(8))//26岁
34、实现字符串反转的方法
var str = "abcdef";
console.log( str.split("").reverse().join("") );//fedcba
35、js的延迟加载方式
<1>使用setTimeout延迟方法的加载时间
<script type="text/javascript" >
function A(){
$.post("/lord/login",{name:username,pwd:password},function(){
alert("Hello");
});
}
$(function (){
setTimeout('A()', 1000); //延迟1秒
})
</script>
<2><script>标签定义defer属性(HTML4)
<script src="test1.js" defer="defer"></script>
<3><script>标签定义 async属性(HTML5)
<script src="test2.js" async></script>
<4>让js最后加载
把js外部引入的文件放到页面底部,来让js最后引入,从而加快页面加载速度
<5>使用jQuery的getScript()方法
$.getScript("outer.js",function(){//回调函数,成功获取文件后执行的函数
console.log("脚本加载完成")
});
36、JavaScript常见的内置对象
Object,Math,String,Array,Number,Function,Boolean,JSON
37、JS的事件冒泡和事件捕获
事件捕获指的是从document到触发事件的那个节点,即自上而下的去触发事件。相反的,事件冒泡是自下而上的去触发事件。绑定事件方法的第三个参数,就是控制事件触发顺序是否为事件捕获。true,事件捕获;false,事件冒泡。默认false,即事件冒泡。Jquery的e.stopPropagation会阻止冒泡,意思就是到我为止,我的爹和祖宗的事件就不要触发了。
<div id="parent">
<div id="child" class="child"></div>
</div>
document.getElementById("parent").addEventListener("click",function(e){
alert("parent事件被触发,"+this.id);
}) document.getElementById("child").addEventListener("click",function(e){
alert("child事件被触发,"+this.id)
})
结果:(先child,然后parent。事件的触发顺序自内向外,这就是事件冒泡。)
child事件被触发,child
parent事件被触发,parent
现在改变第三个参数的值为true,意思为事件捕获
结果:(先parent,然后child。事件触发顺序变更为自外向内,这就是事件捕获。)
parent事件被触发,parent
child事件被触发,child
三、VUE框架部分
1、v-show指令和v-if指令的区别?
条件渲染指令,与v-if不同的是,无论v-show的值为true或者false,元素都会存在于HTML代码中,而v-if只有在为true时才会在HTML代码中存在,v-show设置css的style值
2、<style scoped></style>css代码只在当前组件起作用
3、指令keep-alive含义:在vue-router中写keep-alive保留状态,避免重新渲染
4、Vue.js特点:
简洁:页面由HTML模板+Json数据+Vue实例组成
数据驱动:自动计算属性和追踪依赖的模板表达式
组件化:用可复用、解耦的组件来构造页面
轻量:代码量小,不依赖其他库
快速:精确有效批量DOM更新
模板友好:可通过npm,bower等多种方式安装,很容易融入
5、vue的常用指令有哪些?
v-if、v-show、v-else、v-for、v-bind、v-on、v-model
8、vuex核心概念?
state => 基本数据
getters => 从基本数据派生的数据
mutations => 提交更改数据的方法,同步!
actions => 像一个装饰器,包裹mutations,使之可以异步。
modules => 模块化Vuex
10、怎么定义vue-router的动态路由?怎么获取传过来的动态参数?
答:在router目录下的index.js文件中,对path属性加上/:id。 使用router对象的params.id
11、vue-router有哪几种导航钩子?
第一种:是全局导航钩子:router.beforeEach(to,from,next),作用:跳转前进行判断拦截。
第二种:组件内的钩子;
第三种:单独路由独享组件
12、mint-ui是什么?怎么使用?说出至少三个组件使用方法?
答:基于vue的前端组件库。npm安装,然后import样式和js,
vue.use(mintUi)全局引入。在单个组件局部引入:import {Toast} from ‘mint-ui’。
组件一:Toast(‘登录成功’);
组件二:mint-header;
组件三:mint-swiper
13、axios是什么?怎么使用?描述使用它实现登录功能的流程?
答:请求后台资源的模块。npm install axios -S装好,
然后发送的是跨域,需在配置文件中config/index.js进行设置。
后台如果是Tp5则定义一个资源路由。js中使用import进来,
然后.get或.post。返回在.then函数中如果成功,
失败则是在.catch函数中
14、vuex是什么?怎么使用?哪种功能场景使用它?
答:vue框架中状态管理。在main.js引入store,注入。
新建了一个目录store,….. export 。
场景有:单页应用中,组件之间的状态。音乐播放、登录状态、加入购物车
15、mvvm框架是什么?它和其它框架(jquery)的区别是什么?哪些场景适合?
答:一个model+view+viewModel框架,数据模型model,viewModel连接两个
区别:vue数据驱动,通过数据来显示视图层而不是节点操作。
场景:数据操作比较多的场景,更加便捷
16、自定义指令(v-check、v-focus)的方法有哪些?它有哪些钩子函数?还有哪些钩子函数参数?
答:全局定义指令:在vue对象的directive方法里面有两个参数,一个是指令名称,另外一个是函数。组件内定义指令:directives钩子函数:bind(绑定事件触发)、inserted(节点插入的时候触发)、update(组件内相关更新)钩子函数参数:el、binding
17、说出至少4种vue当中的指令和它的用法?
答:v-if:判断是否隐藏;v-for:数据循环出来;v-bind:class:绑定一个属性;v-model:实现双向绑定
18、Vue的双向数据绑定原理是什么?
答:vue.js 是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
具体步骤:
第一步:需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter
这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
第二步:compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
第三步:Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:1、在自身实例化时往属性订阅器(dep)里面添加自己2、自身必须有一个update()方法3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
第四步:MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。
19、请详细说下你对vue生命周期的理解?
答:总共分为8个阶段创建前/后,载入前/后,更新前/后,销毁前/后。
创建前/后: 在beforeCreated阶段,vue实例的挂载元素$el和数据对象data都为undefined,还未初始化。在created阶段,vue实例的数据对象data有了,$el还没有。
载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。
更新前/后:当data变化时,会触发beforeUpdate和updated方法。
销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在
20、请说下封装 vue 组件的过程?
答:首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性等问题。
然后,使用Vue.extend方法创建一个组件,然后使用Vue.component方法注册组件。子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。
21、vue-loader是什么?使用它的用途有哪些?
答:解析.vue文件的一个加载器,跟template/js/style转换成js模块。
用途:js可以写es6、style样式可以scss或less、template可以加jade等
22、请说出vue.cli项目中src目录每个文件夹和文件的用法?
答:assets文件夹是放静态资源;components是放组件;router是定义路由相关的配置;view视图;app.vue是一个应用主组件;main.js是入口文件
23、聊聊你对Vue.js的template编译的理解?
答:简而言之,就是先转化成AST树,再得到的render函数返回VNode(Vue的虚拟DOM节点)
详情步骤:
首先,通过compile编译器把template编译成AST语法树(abstract syntax tree 即 源代码的抽象语法结构的树状表现形式),compile是createCompiler的返回值,createCompiler是用以创建编译器的。另外compile还负责合并option。
然后,AST会经过generate(将AST语法树转化成render funtion字符串的过程)得到render函数,render的返回值是VNode,VNode是Vue的虚拟DOM节点,里面有(标签名、子节点、文本等等)
24、vue的组件是怎么定义的?父组件怎么给子组件传值?
答:首先注册vue.components,第一个参数是组件名称,第二个参数是选项。
直接绑定一个属性,然后在子组件props里面接收
27、说下你对mvvm的理解?双向绑定的理解?
答:mvvm就是vm框架视图、m模型就是用来定义驱动的数据、v经过数据改变后的html、vm就是用来实现双向绑定
双向绑定:一个变了另外一个跟着变了,例如:视图一个绑定了模型的节点有变化,模型对应的值会跟着变
25、请说下具体使用vue的理解?
1、使用vue不必担心布局更改和类名重复导致的js重写,因为它是靠数据驱动双向绑定,底层是通过Object.defineProperty() 定义的数据 set、get 函数原理实现。2、组件化开发,让项目的可拓展性、移植性更好,代码重用性更高,就好像农民工建房子,拿起自己的工具包就可以开工。项目经理坐等收楼就好。3、单页应用的体验零距离接触安卓原生应用,局部组件更新界面,让用户体验更快速省时。4、js的代码无形的规范,团队合作开发代码可阅读性更高。
26、你觉得哪些项目适合vue框架?
答:1、数据信息量比较多的,反之类似企业网站就无需此框架了。2、手机web和app应用多端共用一套界面的项目,因为使用vue.cli+webpack后的前端目录,非常有利于项目的跨平台部署。
27、怎么理解MVVM模式的这些框架?
答:1、M就是Model模型层,存的一个数据对象。2、V就是View视图层,所有的html节点在这一层。3、VM就是ViewModel,它通过data属性连接Model模型层,通过el属性连接View视图层。
28、vuex有哪几种属性?
答:有五种,分别是 State、 Getter、Mutation 、Action、 Module
29、vuex的State特性是?
一、Vuex就是一个仓库,仓库里面放了很多对象。其中state就是数据源存放地,对应于与一般Vue对象里面的data
二、state里面存放的数据是响应式的,Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新
三、它通过mapState把全局的 state 和 getters 映射到当前组件的 computed 计算属性中
30、vuex的Getter特性是?
一、getters 可以对State进行计算操作,它就是Store的计算属性
二、 虽然在组件内也可以做计算属性,但是getters 可以在多组件之间复用
三、 如果一个状态只在一个组件内使用,是可以不用getters
31、vuex的Mutation特性是?
一、Action 类似于 mutation,不同在于:
二、Action 提交的是 mutation,而不是直接变更状态。
三、Action 可以包含任意异步操作
32、Vue.js中ajax请求代码应该写在组件的methods中还是vuex的actions中?
1>如果请求来的数据是不是要被其他组件公用,仅仅在请求的组件内使用,就不需要放入vuex 的state里。
2>如果被其他地方复用,这个很大几率上是需要的,如果需要,请将请求放入action里,方便复用,并包装成promise返回,在调用处用async await处理返回的数据。如果不要复用这个请求,那么直接写在vue文件里很方便。
33、不用Vuex会带来什么问题?
一、可维护性会下降,你要想修改数据,你得维护三个地方
二、可读性会下降,因为一个组件里的数据,你根本就看不出来是从哪来的
三、增加耦合,大量的上传派发,会让耦合性大大的增加,本来Vue用Component就是为了减少耦合,现在这么用,和组件化的初衷相背。
34、第一次页面加载会触发哪几个钩子?
答:第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子
35、简单描述每个周期具体适合哪些场景?
答:生命周期钩子的一些使用方法: beforecreate : 可以在这加个loading事件,在加载实例时触发 created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用 mounted : 挂载元素,获取到DOM节点 updated : 如果对数据统一处理,在这里写上相应函数 beforeDestroy : 可以做一个确认停止事件的确认框 nextTick : 更新数据后立即操作dom
36、axios的特点有哪些?
1>、Axios 是一个基于 promise 的 HTTP 库,支持promise所有的API
2>、它可以拦截请求和响应
3>、它可以转换请求数据和响应数据,并对响应回来的内容自动转换成 JSON类型的数据
4>、安全性更高,客户端支持防御 XSRF
37、axios有哪些常用方法?
一、axios.get(url[, config]) //get请求用于列表和信息查询
二、axios.delete(url[, config]) //删除
三、axios.post(url[, data[, config]]) //post请求用于信息的添加
四、axios.put(url[, data[, config]]) //更新操作