HTML
- 行内元素、块级元素、空元素有哪些?
首先我们得了解一下这各种元素是什么,css规定每个元素都应该有默认的display的值。值为inline的就是行内元素,block则是块级元素。行内元素与其他元素共占一行,无法给它们设定宽高和上下边距(设置了也不会生效);块级元素则是独占一行,可以设定宽高和上下左右边距。空元素则是指元素中间没有内容,类似于单标签元素(注意,没有内容是指在html代码中而不是在页面上没有内容)。欢迎补充
行内元素:a,b,span,img,input,strong,select,label,em,button
块级元素:div,ul,li,dl,h系列,p,table,blockquote,form,ol
空元素:img,hr,br,link,meta,source,input
CSS
- link和@import的区别
我们都知道,外部引入 CSS 有2种方式,link
标签和@import
。
- 作用上:link是HTML的一个标签,不只是用来引入CSS文件,还可以定义 RSS、rel 连接属性等。而@import是css提供的语法规则,只用于导入样式表。
- 加载顺序的区别:加载页面时,由link引入的CSS文件被同时加载,而用import方法则在页面加载完毕以后再加载。
- 兼容性区别:link是HTML元素,在哪都能用;而link是CSS2.1才有的语法,IE5+才能用。不过现在基本上已经被全面支持。
- DOM操作可控性:前面说了,link是html标签,js能进行DOM操作,因此也能给页面添加link标签引入新的文件;而import就无法进行这样的操作了。
- 权重争议:这个问题由于时间关系本人在书写这部分内容时无法进行验证,请大家自行探索,涉及加载先后和浏览器工作的问题。
- css样式优先级计算
css样式优先级就涉及到了多种选择器,像是标签选择器、类选择器等,以下列出各种选择器的权重。
- 用户设定的浏览器样式:可以认为权重最最低,只有当完全没有设定样式时才会使用。
- 标签选择器:如p、div等,权重为 1 。
- 类选择器:如.container,权重为 10。
- id选择器:如#id,权重为100。
- 内联样式:写在html元素中的样式,权重为1000。
计算样式优先级的时候,根据该样式有对应的选择器,将所有的样式权重相加,数字大的则优先显示。权重相同时则按样式书写的先后进行显示。
PS:如height:100px!important;出现了 !important 字眼,则说明这个样式超越了权重,它有最高的优先级(不管其它的样式权重多大)。
- css的盒模型
首先要理解盒模型的概念:盒模型就是页面看上去元素的内容、内外边距、边框等内容组成的一张平面图,反应元素整体和各部分的宽高。
盒模型分为两种,一种是W3C的标准盒模型,这种模型定义了宽高是固定的,就算我们给他定义了内边距以及边框,也不会改变元素的宽高,但是外边距会改变它与其他元素的距离;另一个种是IE的盒模型,我们给元素定义的宽高仅仅只是指元素内容的宽高,再定义内边距和边框,那么元素会变大,与我们预期的有差别。
- 试试
JS
- js有的基本数据类型(具体细节后面下班回去再整理)
js有的基本类型其实和其他的语言很相似,有Number、String、Boolean、null、undefined和object这些基本类型。
其中,null和undefined是由object派生而来的类型,对null进行typeof操作,返回object字眼。null和undefined这两个类型只有一个值,就是null和undefined。
- 使用new操作符发生了什么
function Func(){
this.age = 1;
};
var newFunc=new Func ();
new操作符相信大家都知道通常在新建一个对象实例时使用。但是它实际上并没有这么简单。红宝书上面写了有四个过程,我这里把它搬过来。
function Func(){
this.age = 1;
};
var newFunc=new Func ();
var obj = new Object(); //1.创建一个新对象,并设置新对象的原型链
obj.__proto__ = Func.__proto__
Func.call(obj); //2.将构造函数的作用域赋给了新对象(此时this指向了新对象)
obj.age = 1; //3.给新对象设定属性和方法
return obj; //4.将新建的对象obj返回
- call()和apply()方法
这两个方法这里就不细致说如何使用了,搜一下有很多的文章讲这些。个人觉得这两个方法的作用真正理解应该是:传入一个执行上下文,代替原先的执行上下文,也就是this指向的改变,或者可以说是作用域链(可参考高性能JavaScript这本书讲到的作用域链)的第一个作用域的修改。
此外这两个方法的区别是在从第二个参数起的部分。我们有时候使用类数组对象arguments来使用没有显式声明的函数参数。但是这个技巧在call方法不能使用,所有要使用的参数都得显示声明好;而apply方法可以使用arguments来灵活使用参数。
- eval()方法是做啥的?
这个方法可以将传入的参数(字符串)解析成js代码,然后马上执行。但我们不只是该关注这个解析字符串的点。
如果eval接收的参数不是字符串,那么它将原封不动的返回参数。此外,使用eval的开销非常大。大部分文章提到它要先解析字符串称为JavaScript代码,然后执行,因此消耗大。但是它背后的原理是什么?下面简单说一下
js执行的时候,会形成一个作用域链的东西,查询读取变量的时候就是根据作用域链一直往上查询直到全局的global对象(浏览器里面是window)。这意味着,我们所要的变量离当前作用域越远,那么访问它的代价就更大(因为查找的开销比较大)。而eval方法在执行的时候,会马上建立一个新的作用域,并将这个作用域放在作用域链的最前面(类似于链表头部插入一个节点),这个时候之前的所有变量会离我们当前的作用域更远,也就是访问时会有更大的开销。所以eval执行的时候会比普通的代码消耗更大。
eval还存在安全问题。
- 变量提升是什么?为什么会出现这种情况?
变量提升是指:在变量未曾声明之前调用该变量,但是不会报错。例如:
console.log(a); //undefined
var a = 6;
可以看到,这个语句没有报错,而且输出了undefined,这是变量只声明而没有赋值的情况。这是因为浏览器执行脚本的时候,会先检查一遍代码,先执行声明语句,再执行其他的语句。也就是说,上面代码其实等同于
var a;
console.log(a);
a = 6;
- typeof返回哪些数据类型
string、Boolean、number、undefined、object、function(注意 typeof null 会返回object)
- 显式和隐式类型转换
显式:number系列(parseInt,parseFloat,Number),同理String(),欢迎补充。注意toString()是一个方法,而不是类型转换的一种。(每个数据类型都有它对应的类,当我们调用一个类型的toString()方法时,浏览器会创建一个该类型的对象,然后调用该对象的toString方法)
隐式:==(等于号),+string(比如 +“1”能够把字符串类型的1变成数字)
- 事件委托的概念
事件委托即是将事件处理方法注册在另外一个元素上,通过目标元素触发事件后,可以通过冒泡或者捕获机制,等待事件传递到另一个元素上,由另一个元素执行这个处理方法。
比如说,某个父元素下有很多个子元素按钮,那么如果我们为每个按钮都注册点击事件(每个按钮都需要一个监听器),那么这样引起的性能开销是非常庞大的;我们可以给这些按钮的父元素注册点击事件,让他监听子元素的点击。然后使用event事件参数的target就能获得是哪个按钮被点击。(PS:这里可以顺便查一下event对象的详细知识)
- 前端跨域方法jsonp是什么?和ajax有什么不同?
浏览器有同源限制,当我们发送请求的目标服务器需要突破这个同源限制的时候就形成了跨域。浏览器默认不允许跨域(毕竟都有同源限制了,要是允许跨域哪来的同源限制)。不过对于HTML标签的src属性,浏览器不对其进行限制。那么这就有机可乘了。
jsonp是跨域方法的一种,利用的就是src属性能避开浏览器的限制这个特点。首先,jsonp在页面中创建一个script标签。然后给script标签设置src路径(像是get请求那样在路径里面包含要传递的数据和一个回调方法)。如下:
var scriptTag = document.createElement("script");
body.append(scriptTag);
scriptTag.scr = "www.xxxx.com?id=xxx&password=xxx&callback=handleData";
//服务器根据我们发送的数据处理完之后,返回一个 handleData(data); 这样的JS语句
//另一个地方定义了handleDAta方法
function handleData(data){
console.log(data);
}
这就等同于,我们在script标签里面调用了handleData的回调函数,这里的callback就是告诉服务器该调用哪个函数。时间关系写的不详细,具体知识可以自己学习。
可以看到,虽然我们像浏览器发送了请求,但是,实际上这个请求是浏览器的默认执行操作,看到src就自动去获取该路径的值,并且回调函数并不是由我们执行,而是由服务器返回的脚本执行。这样就存在安全隐患,万一服务器返回别的脚本呢?就算你信任你的服务器,万一请求在中途被拦截了呢?
- window.onload和document.ready的区别
简单来说,浏览器加载一个页面的过程是①加载html ②加载JS和CSS文件 ③加载图片(其实这个过程有些交错进行,具体细节还很多)。onload方法就是在第三步,就是页面所有内容都加载完毕后执行,ready方法则是在第一步即是完成页面结构后就执行。其实可以看到window本身就比document的范围要大,从可这个方面去理解。
- JavaScript的事件流模型
浏览器触发事件,这个事件从发生到传递到各个属性的过程就是事件流模型。说的比较抽象, 其实就是冒泡和捕获这些。
事件冒泡:从目标元素开始,事件逐步往上传递给父元素的过程;事件捕获:由最外面的父元素开始直到传递给到目标子元素。而事件流实际上被划分为三个阶段:捕获阶段==>处于目标阶段==>冒泡阶段。事件流模型的应用就是上面说到的事件委托。更详细的内容等我看完红宝书这一部分再进行补充。
- 关于作用域上下文(this)的理解
var User = {
count: 1,
getCount: function() {
return this.count;
}
};
console.log(User.getCount()); // what?
var func = User.getCount;
console.log(func()); // what?
问两处console输出什么?为什么?
答案:是1和undefined。
func是在window的上下文中被执行的,所以不会访问到count属性。
个人觉得这this的理解可以用前面提到的作用域链来解释。第一个输出语句,对于getCount来说,执行的时候,位于作用域链最前面的就是User对象的作用域,this指向了User对象,于是在这里访问count就是1。而第二个输出语句的时候,getCount的运行作用域就是全局,也就是说this指向的就是全局对象window,但是全局上并没有找到count属性,所以返回undefined
- ajax的流程
(1)创建一个XMLHTTPRequest对象
var xhr = new XMLHttpRequest();
(2)打开请求
xhr.open('GET', 'example.txt', true);
(3)发送请求
xhr.send(); //发送请求到服务器
(4)监听readystate值的变化来决定执行的操作。
xhr.onreadystatechange =function(){}
(1)当readystate值从一个值变为另一个值时,都会触发readystatechange事件。
(2)当readystate==4时,表示已经接收到全部响应数据。
(3)当status ==200时,表示服务器成功返回页面和数据。
(4)如果(2)和(3)内容同时满足,则可以通过xhr.responseText,获得服务器返回的内容。
- 多大
其他
- 浏览器工作原理:查看大佬写的文章:https://kb.cnblogs.com/page/129756/
- 达到