一、左固定右自适应布局
二、清除浮动的方式
三、js继承
1、简单原型链——拿父类的实例充当子类的原型对象
具体实现:
function Super(){
this.val = 1;
this.arr = [1];
}
function Sub(){
// ...
}
Sub.prototype = new Super(); // 核心
var sub1 = new Sub();
var sub2 = new Sub();
sub1.val = 2;
sub1.arr.push(2);
alert(sub1.val); // 2
alert(sub2.val); // 1
alert(sub1.arr); // 1, 2
alert(sub2.arr); // 1, 2
优点:简单易于实现
缺点:
(1)修改sub1.arr后sub2.arr也变了,因为来自原型对象的引用属性是所有实例共享的。如以上代码的最后两句。
(2)创建子类实例时,无法向父类构造函数传参
2、借用构造函数——借父类的构造函数来增强子类实例,等于是把父类的实例属性复制了一份给子类实例装上了(完全没有用到原型)
具体实现:
function Super(val){
this.val = val;
this.arr = [1];
this.fun = function(){
// ...
}
}
function Sub(val){
Super.call(this, val); // 核心
// ...
}
var sub1 = new Sub(1);
var sub2 = new Sub(2);
sub1.arr.push(2);
alert(sub1.val); // 1
alert(sub2.val); // 2
alert(sub1.arr); // 1, 2
alert(sub2.arr); // 1
alert(sub1.fun === sub2.fun); // false
优点:
(1)解决了子类实例共享父类引用属性的问题
(2)创建子类实例时,可以向父类构造函数传参
缺点:无法实现函数复用,每个子类实例都持有一个新的fun函数,太多了就会影响性能,内存爆炸。
3、组合继承(最常用)——把实例函数都放在原型对象上,以实现函数复用。同时还要保留借用构造函数方式的优点,通过Super.call(this);继承父类的基本属性和引用属性并保留能传参的优点;通过Sub.prototype = new Super();继承父类函数,实现函数复用
具体实现:
function Super(){
// 只在此处声明基本属性和引用属性
this.val = 1;
this.arr = [1];
}
// 在此处声明函数
Super.prototype.fun1 = function(){};
Super.prototype.fun2 = function(){};
//Super.prototype.fun3...
function Sub(){
Super.call(this); // 核心
// ...
}
Sub.prototype = new Super(); // 核心
var sub1 = new Sub(1);
var sub2 = new Sub(2);
alert(sub1.fun === sub2.fun); // true
优点:
(1)不存在引用属性共享问题
(2)可传参
(3)函数可复用
缺点:(一点小瑕疵)子类原型上有一份多余的父类实例属性,因为父类构造函数被调用了两次,生成了两份,而子类实例上的那一份屏蔽了子类原型上的。。。又是内存浪费
4、原型式——用生孩子函数得到得到一个“纯洁”的新对象(“纯洁”是因为没有实例属性),再逐步增强之(填充实例属性)
具体实现:
function beget(obj){ // 生孩子函数 beget:龙beget龙,凤beget凤。
var F = function(){};
F.prototype = obj;
return new F();
}
function Super(){
this.val = 1;
this.arr = [1];
}
// 拿到父类对象
var sup = new Super();
// 生孩子
var sub = beget(sup); // 核心
// 增强
sub.attr1 = 1;
sub.attr2 = 2;
//sub.attr3...
alert(sub.val); // 1
alert(sub.arr); // 1
alert(sub.attr1); // 1
优点:从已有对象衍生新对象,不需要创建自定义类型(更像是对象复制,而不是继承。。)
缺点:
(1)原型引用属性会被所有实例共享,因为是用整个父类对象来充当了子类原型对象,所以这个缺陷无可避免
(2)无法实现代码复用(新对象是现取的,属性是现添的,都没用函数封装,怎么复用)
5、寄生式——给原型式继承穿了个马甲而已,看起来更像继承了
具体实现:
function beget(obj){ // 生孩子函数 beget:龙beget龙,凤beget凤。
var F = function(){};
F.prototype = obj;
return new F();
}
function Super(){
this.val = 1;
this.arr = [1];
}
function getSubObject(obj){
// 创建新对象
var clone = beget(obj); // 核心
// 增强
clone.attr1 = 1;
clone.attr2 = 2;
//clone.attr3...
return clone;
}
var sub = getSubObject(new Super());
alert(sub.val); // 1
alert(sub.arr); // 1
alert(sub.attr1); // 1
优点:还是不需要创建自定义类型
缺点:无法实现函数复用(没用到原型,当然不行)
6、寄生组合继承(最佳方式)——用beget(Super.prototype);切掉了原型对象上多余的那份父类实例属性
具体实现:
function beget(obj){ // 生孩子函数 beget:龙beget龙,凤beget凤。
var F = function(){};
F.prototype = obj;
return new F();
}
function Super(){
// 只在此处声明基本属性和引用属性
this.val = 1;
this.arr = [1];
}
// 在此处声明函数
Super.prototype.fun1 = function(){};
Super.prototype.fun2 = function(){};
//Super.prototype.fun3...
function Sub(){
Super.call(this); // 核心
// ...
}
var proto = beget(Super.prototype); // 核心
proto.constructor = Sub; // 核心
Sub.prototype = proto; // 核心
var sub = new Sub();
alert(sub.val);
alert(sub.arr);
四、javascript 删除 url 中指定参数,并返回 url
javascript 删除 url 中指定参数,并返回 url
提示用正则表达式获取,不要用分割字符串的方法
五、盒子居中
六、判断数组类型
七、闭包的定义,手写一个闭包的例子
闭包及其在什么地方运用
首先来看一个闭包demo:
function A(){
function B(){
console.log("Hello world");
}
return B;
}
var C=A();
C();//Hello wprld
有了初步认识后,我们简单分析一下它和普通函数有什么不同,上面代码翻译成自然语言如下:
(1)定义普通函数 A
(2)在 A 中定义普通函数 B
(3)在 A 中返回 B
(4)执行 A, 并把 A 的返回结果赋值给变量 C
(5)执行 C
把这5步操作总结成一句话就是:
函数A的内部函数B被函数A外的一个变量 c 引用。
把这句话再加工一下就变成了闭包的定义:
当一个内部函数被其外部函数之外的变量引用时,就形成了一个闭包。
因此,当你执行上述5步操作时,就已经定义了一个闭包!
闭包的用途:
首先了解一个知识点:
在 Javascript 中,如果一个对象不再被引用,那么这个对象就会被 GC (垃圾回收机制)回收,否则这个对象一直会保存在内存中。
在上述例子中,B定义在A中,因此B依赖于A,而外部变量C又引用了B,所以A间接的被C引用。也就是说A不会被GC回收,会一直保存 在内存中。为了证明我们的推理,上面的例子稍作改进:
function A(){
var count=0;
function B(){
count++;
console.log(count);
}
return;
}
var C = A();
C();// 1
C();// 2
C();// 3
所以当我们需要在模块中定义一些变量,并希望这些变量一直保存在内存中但又不会“污染”全局的变量时,就可以用闭包来定义这个模块。
八、重绘(redraw)和重排(也叫回流reflow)以及优化方法
重绘:是一个元素的外观变化所引发的浏览器行为;例如改变visibility、outline、背景色等属性。
重排:是引起DOM树重新计算的行为;
何时发生重排:
1、添加或者删除可见的DOM元素;
2、元素位置改变;
3、元素尺寸改变——边距、填充、边框、宽度和高度
4、内容改变——比如文本改变或者图片大小改变而引起的计算值宽度和高度改变;
5、页面渲染初始化;
6、浏览器窗口尺寸改变——resize事件发生时;
如何减少回流、重绘:
1、将多次dom修改合并成一次操作
2、多次重排的元素,先脱离文档流,在修改
3、display属性为none,减少重排
4、 在需要经常获取那些引起浏览器重排的属性值时,要缓存到变量
九、为什么静态页面会单独存储
1、避免域名污染
2、以减少请求,提高网页性能
十、HTML5新增和移除元素
canvas新元素
JavaScript 的绘图 API
新多媒体元素
audio 定义音频内容
video 定义视频(video 或者 movie)
source 定义多媒体资源 video 和 audio
embed 定义嵌入的内容,比如插件。
track 为诸如 video 和 audio 元素之类的媒介规定外部文本轨道。
新表单元素
datalist 定义选项列表。请与 input 元素配合使用该元素,来定义 input 可能的值。
keygen 规定用于表单的密钥对生成器字段。
output 定义不同类型的输出,比如脚本的输出。
新的语义和结构元素
HTML5提供了新的元素来创建更好的页面结构:
标签 描述
article —定义页面独立的内容区域。
aside —定义页面的侧边栏内容。
bdi —允许您设置一段文本,使其脱离其父元素的文本方向设置。
command— 定义命令按钮,比如单选按钮、复选框或按钮
details —用于描述文档或文档某个部分的细节
dialog —定义对话框,比如提示框
summary— 标签包含 details 元素的标题
figure— 规定独立的流内容(图像、图表、照片、代码等等)。
figcaption —定义 figure 元素的标题
footer —定义 section 或 document 的页脚。
header— 定义了文档的头部区域
mark —定义带有记号的文本。
meter —定义度量衡。仅用于已知最大和最小值的度量。
nav —定义导航链接的部分。
progress —定义任何类型的任务的进度。
ruby —定义 ruby 注释(中文注音或字符)。
rt —定义字符(中文注音或字符)的解释或发音。
rp —在 ruby 注释中使用,定义不支持 ruby 元素的浏览器所显示的内容。
section —定义文档中的节(section、区段)。
time —定义日期或时间。
wbr —规定在文本中的何处适合添加换行符。
已移除的元素
以下的 HTML 4.01 元素在HTML5中已经被删除:
<acronym>
<applet>
<basefont>
<big>
<center>
<dir>
<font>
<frame>
<frameset>
<noframes>
<strike>
<tt>
十一、如何 把字符串分割成字符串数组
JavaScript split() 方法
作用:用于把一个字符串分割成字符串数组
语法:stringObject.split(separator,howmany)
参数1:separator必选,字符串或正则表达式,从该参数指定的地方分割 stringObject
参数2:howmany可选,该参数可指定返回的数组的最大长度。如果设置了该参数,返回的子串不会多于这个参数指定的数组。如果没有设置该参数,整个字符串都会被分割,不考虑它的长度
十二:push()、pop()和unshift()、shift()的用法
1、push()、pop()类似于栈的先进后出
pop:删除原数组最后一项,并返回删除元素的值;如果数组为空则返回undefined
var a = [1,2,3,4,5];
var b = a.pop(); //a:[1,2,3,4] b:5
push:将参数添加到原数组末尾,并返回数组的长度
var a = [1,2,3,4,5];
var b = a.push(6,7); //a:[1,2,3,4,5,6,7] b:7
2、shift和unshift类似于队列的先进先出:
shift:删除原数组第一项,并返回删除元素的值;如果数组为空则返回undefined
var a = [1,2,3,4,5];
var b = a.shift(); //a:[2,3,4,5] b:1
unshift:将参数添加到原数组开头,并返回数组的长度
var a = [1,2,3,4,5];
var b = a.unshift(-2,-1); //a:[-2,-1,1,2,3,4,5] b:7
十三、怎么获取URL地址
window.location方法获取URL
示例:
http://www.home.com:8080/windows/location/page.html?ver=1.0&id=timlq#love
1、 window.location.href
整个URl字符串(在浏览器中就是完整的地址栏)
返回值:http://www.home.com:8080/windows/location/page.html?ver=1.0&id=timlq#love
2、window.location.protocol
URL 的协议部分
返回值:http:
3、window.location.host
URL 的主机部分,
返回值:www.home.com
4、window.location.port
URL 的端口部分。如果采用默认的80端口(update:即使添加了:80),那么返回值并不是默认的80而是空字符。
返回值:8080
5、window.location.pathname
URL 的路径部分(就是文件地址)
返回值:/windows/location/page.html
6、window.location.search
查询(参数)部分。除了给动态语言赋值以外,我们同样可以给静态页面,并使用javascript来获得相信应的参数值
返回值:?ver=1.0&id=timlq
7、window.location.hash
锚点
返回值:#love
十四、HTTP协议有几种请求方法
1、OPTIONS
返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性
2、HEAD
向服务器索与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。
3、GET
向特定的资源发出请求。注意:GET方法不应当被用于产生“副作用”的操作中,例如在Web Application中,其中一个原因是GET可能会被网络蜘蛛等随意访问。Loadrunner中对应get请求函数:web_link和web_url
4、POST
向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 Loadrunner中对应POST请求函数:web_submit_data,web_submit_form
5、PUT
向指定资源位置上传其最新内容
6、DELETE
请求服务器删除Request-URL所标识的资源
7、TRACE
回显服务器收到的请求,主要用于测试或诊断
8、CONNECT
HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
十五、get和post的区别是什么?
GET用于获取查询信息,POST用户更新资源信息
GET数据是明文传输,不安全,POST则把数据放到了http包体内。
GET提交数据有一定限制,POST则没有限制
GET 方法 :
- GET 请求可被缓存
- GET 请求保留在浏览器历史记录中
- GET 请求可被收藏为书签
- GET 请求不应在处理敏感数据时使用
- GET 请求有长度限制
- GET 请求只应当用于取回数据
post 方法 :
- POST 请求不会被缓存
- POST 请求不会保留在浏览器历史记录中
- POST 不能被收藏为书签
- POST 请求对数据长度没有要求
其他 HTTP 请求方法:
十六、用过css 预处理吗,了解多少?
十七、Transitions、Translate、transform的区别和联系
transition(过渡效果):
语法:
transition: property duration timing-function delay;
translate(移动):
语法:
translate(dx, dy)
transform(变形):
语法:
transform: none|transform-functions;
提供了几个很有用的属性来改变元素的形状:缩放scale,旋转rotate,倾斜skew
animation(动画)
语法:
animation: name duration timing-function delay iteration-count direction;
十八、说说关于原生js的了解和你知道的js衍生的框架和库
提示:原生js规范之类的
框架:Vue.js、Node.Js、angular.Js、React
库:Jquery 、bootstrap
十九、说说js和ECMAscript的关系
ECMAScript是JavaScript的规范,JavaScript是ECMAScript的实现。
二十、说说对ES6的理解
es6是一个新的标准,它包含了许多新的语言特性和库,是JS最实质性的一次升级。
比如’箭头函数’、’字符串模板’、’generators(生成器)’、’async/await’、’解构赋值’、’class’等等,还有就是引入module模块的概念。
二十一、ES6的特性
1.函数参数的默认值可以直接放到函数声明里
var link = function(height = 50, color = 'red', url = 'http://azat.co') {
...
}
2.模板对象
var name = `Your name is ${first} ${last}. `;
var url = `http://localhost:3000/api/messages/${id}`;
3.箭头函数
有了箭头函数在ES6中, 我们就不必用that =this或 self= this或 _this=this 或.bind(this)
$('.btn').click((event) =>{
this.sendData();
})
4.块级作用域和构造let、const
5.Class类
class baseModel {
constructor(options, data) { // class constructor,node.js 5.6暂时不支持options = {}, data = []这样传参
this.name = 'Base';
this.url = 'http://azat.co/api';
this.data = data;
this.options = options;
}
getName() { // class method
console.log(`Class name: ${this.name}`);
}
}
//继承
class AccountModel extends baseModel {
constructor(options, data) {
super({private: true}, ['32113123123', '524214691']); //call the parent method with super
this.name = 'Account Model';
this.url +='/accounts/';
}
get accountsData() { //calculated attribute getter
// ... make XHR
return this.data;
}
}
//调用
let accounts = new AccountModel(5);
accounts.getName();
console.log('Data is %s', accounts.accountsData);
6.Modules(模块)
ES6中可以用模块import 和export 操作
二十二、事件冒泡和捕获的定义,如何阻止
事件冒泡:
可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。也就是说,事件会从最内层的元素开始发生,一直向上传播,直到document对象。
事件捕获:
与事件冒泡相反,事件会从最外层开始发生,直到最具体的元素。
addEventListener:
element.addEventListener(event, function, useCapture)
第一个参数是需要绑定的事件
第二个参数是触发事件后要执行的函数
第三个参数默认值是false,表示在事件冒泡阶段调用事件处理函数;如果参数为true,则表示在事件捕获阶段调用处理函数。
冒泡案例:
<div id="s1">s1
<div id="s2">s2</div>
</div>
<script>
s1.addEventListener("click",function(e){
console.log("s1 冒泡事件");
},false);
s2.addEventListener("click",function(e){
console.log("s2 冒泡事件");
},false);
</script>
捕获案例:
<div id="s1">s1
<div id="s2">s2</div>
</div>
<script>
s1.addEventListener("click",function(e){
console.log("s1 捕获事件");
},true);
s2.addEventListener("click",function(e){
console.log("s2 捕获事件");
},true);
</script>
当事件捕获和事件冒泡一起存在的情况,事件又是如何触发呢。
- 对于非target节点则先执行捕获在执行冒泡
- 对于target节点则是先执行先注册的事件,无论冒泡还是捕获
阻止方法:
1、在IE浏览器中通过e.cancleBubble=true,阻止事件冒泡。
<html>
<head>
<meta charset="utf-8">
<title>bubble event</title>
<style>
.ele0{
width:400px;
height:400px;
border:1px solid black;
background-color:red;
position:relative;
}
.ele1{
width:300px;
height:300px;
border:1px ;
background-color:green;
position:absolute;
top:0;
}
.ele2{
width:200px;
height:200px;
border:1px ;
background-color:blue;
position:absolute;
top:0;
}
</style>
<script>
window.onload=function(){
var ele=document.getElementsByTagName("div");
if(ele[0].addEventListener)
{
ele[0].addEventListener("click", function (e){
console.log("点击的是盒子ele0!");
e.stopPropagation();
});
}
else{
ele[0].attachEvent("onclick",function (e){
console.log("点击的是盒子ele0!");
e=window.event;
e.cancleBubble=true;
});
}
if(ele[1].addEventListener)
{
ele[1].addEventListener("click", function (e){
console.log("点击的是盒子ele1!");
e.stopPropagation();
});
}
else{
ele[1].attachEvent("onclick",function (e){
console.log("点击的是盒子ele1!");
e=window.event;
e.cancleBubble=true;
});
}
if(ele[2].addEventListener)
{
ele[2].addEventListener("click", function (e){
console.log("点击的是盒子ele2!");
e.stopPropagation();
});
}
else{
ele[2].attachEvent("onclick",function (e){
console.log("点击的是盒子ele2!");
e=window.event;
e.cancleBubble=true;
});
}
}
</script>
</head>
<body>
<div class="ele0">
<div class="ele1"><div class="ele2"></div></div>
</div>
</body>
<html>
2、在除IE以外其他的浏览器中通过e.stopPropagation()方式阻止事件的冒泡
3、stopImmediatePropagation()方法
document.getElementById("second").addEventListener("click",function(){
alert("second");
event.stopImmediatePropagation();
},true);
stopImmediatePropagation() 和 stopPropagation()的区别在哪儿呢?
后者只会阻止冒泡或者是捕获。 但是前者除此之外还会阻止该元素的其他事件发生,但是后者就不会阻止其他事件的发生。
这些只是能记起的,还有好几个一点都不知道的知识点,不记得了
面试官的评价:基础不够好,知识体系不完善,也不够广