经常有大佬问起这方面的问题,现在整理其他博客文章重要知识点,多多背诵
1.基本数据类型
五种: Undefined、 Null、 String、 Number、 Boolean
(数组、函数都属于对象)
(undefined表示变量声明但未初始化时的值,javascript解释器不知道这是什麽东西,会抛出”未定义”的错误
null表示准备用来保存对象,还没有真正保存对象的值。从逻辑角度看,null值表示一个空对象指针,意思是你定义了它,但它没有分配内存空间)
2.JavaScript之面向对象的属性和特征
- 对象的本质:
无序属性的集合,其属性可以包含基本值、对象或者函数;即对象是一组没有特定顺序的值,对象的每个属性或方法都有一个名字,而这个名字都映射到一个值。故对象的本质是一个散列表:其中是一组名值对,值可以是数据或函数。 - 对象的包含:
数据属性和访问器属性,他们的区别如下:- 数据属性: 一般用于存储数据数值,访问器属性不包含数据值;
- 访问器属性: 多用于get/set操作,访问器属性不能直接定义,必须使用Object.defineProperty()来定义,且该属性具有set和ger特性。console对象的时候可看。
3.闭包知识点
- 形成原理:
嵌套函数被返回,被外界的变量引用,或者作为外部属性时,形成闭包。形成之后,原本被调用的属性变量(调用后会被垃圾回收)都能再次被使用,闭包就是能够读取其他函数内部变量的函数。 - 作用(优点)
- 实现共有变量
- 可做缓存
- 保护函数内变量安全,加强封装性,使属性私有化
- 模块化开发,防止污染全局变量
- 缺点:
- 闭包形成,导致原有的作用域链不释放,造成内存泄漏
- 占用内存
- 内存泄漏原因:
- 在闭包的作用域链中引用了HTML元素,导致未释放内存
- 出现了循环引用
4.html页面是如何呈现出来的(或者说经历了哪些步骤)
JavaScript回流(reflow) 与重绘(repaint)
- 如何呈现:
- 1,html文档加载后生成dom树(包括display: none元素);
- 2,在DOM树的基础上配合css样式结构体生成render树(不包含display:none;、head节点,包含visibility:hidden;节点),即页面中的占位确定了,最后绘制页面(也叫渲染),不会改变页面布局的一些属性:color、背景色等。
- 重绘(repaint)
- 更新页面元素的属性引起的,如颜色、透明度等不会改变页面布局而需要重新渲染的。
- 回流(reflow)
- render树中部分或全部元素的尺寸、布局、隐藏等(内容、结构、位置)改变引起的。每个页面至少有一次回流(即初始构建页面时),成本较高。
5.HTTP状态码:
1.消息 2.成功 3.重定向 4.请求错误 5.服务器错误
- 304:响应禁止包含消息体,如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码。
- 305:被请求的资源必须通过指定的代理才能被访问。
- 400:语义有误,当前请求无法被服务器理解。除非进行修改,否则客户端不应该重复提交这个请求,或者请求参数有误。
- 403:服务器已经理解请求,但是拒绝执行它。
- 404:请求失败,请求所希望得到的资源未被在服务器上发现。
- 500:服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理。一般来说,这个问题都会在服务器端的源代码出现错误时出现。
6.Call()和apply()
先认识一下构造函数:
1
2
3
4
5function showname(){
this.name="zygg";
}
var qq=new showname();
console.log(qq.name);call(),apply()可以扩张函数赖以运行的作用域,改变函数内部的this指向,区别就是传参不同
call(thisObj,Object)
apply(thisObj,【argArray】)1
2
3
4
5
6
7
8window.firstName = "diz";
window.lastName = "song";
var myname = { firstName: "my", lastName: "Object" };
function show() {
console.log("Hello " + this.firstName + " " +this.lastName, " glad to meet you!");
}
show();
show.call(myname);//如果不这样写,对象myname是没法调用函数 show()的。
7.浅谈js继承
继承是指一个对象直接使用另一对象的属性和方法
实现方法:
- 对象冒充
- call()与Apply()
- 原型链方式
- js中每个对象均有一个隐藏的proto属性,一个实例化对象的proto属性指向其类的prototype方法,而这个prototype方法又可以被赋值成另一个实例化对象,这个对象的proto又需要指向其类,由此形成一条链。
- 那么proto是什么?我们在这里简单地说下。每个对象都会在其内部初始化一个属性,就是proto,当我们访问一个对象的属性 时,如果这个对象内部不存在这个属性,那么他就会去proto里找这个属性,这个proto又会有自己的proto,于是就这样 一直找下去,也就是我们平时所说的原型链的概念。
8.事件监听机制(冒泡和捕获)
- 事件捕获:事件从最上一级标签开始往下查找(父到子),直到捕获到事件目标(target)。
- 事件冒泡:事件从事件目标(target)开始,从下往上冒泡直到页面的最上一级标签。
假设一个元素div,它有一个下级元素p。1
2
3<div>
<p>元素</p>
</div>
这两个元素都绑定了click事件,如果用户点击了p,它在div和p上都触发了click事件,那这两个事件处理程序哪个先执行呢?
如div先触发,这就叫做事件捕获。
如p先触发,这就叫做事件冒泡。
- IE只支持事件冒泡,其他主流浏览器两种都支持。
- 程序员可以自己选择绑定事件时采用事件捕获还是事件冒泡,方法就是绑定事件时通过addEventListener函数,它有三个参数,第三个参数若是true,则表示采用事件捕获,若是false,则表示采用事件冒泡。
- 事件的传播是可以阻止的:
- 在W3c中,使用stopPropagation()方法
- 在捕获的过程中stopPropagation();后,后面的冒泡过程也不会发生了~
- propagation 【传播,蔓延】
- 阻止事件的默认行为,例如click a标签后的跳转~
- 在W3c中,使用preventDefault()方法;
- 在IE下设置window.event.returnValue = false;
9.js事件委托
- “事件处理程序过多”问题的解决方案就是事件委托。
- 事件委托利用的是事件冒泡机制,只制定一事件处理程序,就可以管理某一类型的所有事件(使用事件委托,只需在DOM树中尽量最高的层次上添加一个事件处理程序)。
- 这里要用到事件源:event 对象,需要用到target属性,其 事件属性可返回事件的目标节点(触发该事件的节点)
1
2
3
4
5
6oUl.onmouseover = function(ev){
var target = ev.target
if(target.nodeName.toLowerCase() == "li"){
target.style.background = "red";
}
}
10.js实现类
- 构造函数:
- 由于js类的定义方法和函数的定义方法一样,所以定义构造函数的同时就定义了类。构造函数内的方法和属性也就是类中的方法和属性。
- 原型
- 该方式利用了对象的prototype属性。首先定义了一个空函数,然后通过prototype属性来定义对象的属性。调用该函数时,原型的所有属性都会立即赋予要创建的对象
11.js自定义事件
- js自定义事件用处较多,最主要的就是实现观察者模式.
观察者模式( 又叫发布者-订阅者模式 )应该是最常用的设计模式之一。
平时接触的dom事件. 也是js和dom之间实现的一种观察者模式.
观察者模式举例:
div.onclick = function click (){
alert ( ‘’click’ )
}
只要订阅了div的click事件. 当点击div的时候, function click就会被触发.Div为发布者,click事件为订阅者 - 自定义事件例子:
1
2
3
4
5
6
7
8
9<script src="Scripts/jquery-2.1.1.min.js"></script>
<script type="text/javascript">
$(function() {
$('body').on('someclick', function () {
console.log('被点击了~~');
});
$('body').trigger('someclick');
});
</script>
on()是jQuery中的类似于bind(),live(),delegate()等绑定事件的方法。
- trigger() 方法触发被选元素的指定事件类型。先给固定元素绑定一个自定义事件”someclick”,然后必须通过trigger()来使自定义事件可以使用。
- Trigger【引发,触发;】
12.回调函数
函数a有一个参数,这个参数是个函数b,当函数a执行完以后执行函数b。那么这个过程就叫回调。函数b是你以参数形式传给函数a的,那么函数b就叫回调函数。回调函数可以继续扩展一个函数的功能,可以是程序非常灵活。1
2
3
4
5
6
7
8
9
10function zy(callback){
alert("开始");
callback();
}
function zygg(){
alert("我是回调函数");
}
function test(){
zy(zygg)
}
13.编程题
有以下两个函数,定义一个对象使其拥有这两个函数属性。
1
2
3
4
5
6
7
8
9
10function mobile(){
return 'mobile';
}
function phone(){
return 'phone';
}
var a = {};
a.mobile = mobile();
a.phone = phone();
console.log(a);数组去重
1
2
3
4
5
6
7
8
9
10
11
12var arr = ['a','g','q','d','a','e','q'];
Array.prototype.unique = function(){
for(var i = 0; i < this.length; i++){
for(var j = i+1; j < this.length; j++){
if(this[i] == this[j]){
this.splice(j,1);
}
}
}
return this;
};
console.log(arr.unique());编写一个函数fn(Number n),将数字转为大写输出,如输入123,输出一百二十三。(这题考察了正则表达式还有数组的操作。)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19function fn (n) {
if(!/^([1-9]\d*)/.text(n)){
return '非法数据';
}
var unit = '千百十亿千百十万千百十个';
if(n.length > unit.length){
return '数据过长';
}
var newStr = '';
var nlength = n.length;
unit = unit.substr(unit.length - nlength);
for(var i = 0; i < nlength; i++){
newStr += '零一二三四五六七八九'.charAt(n[i]) + unit.charAt(i);
}
newStr = newStr.substr(0,newStr.length-1);
newStr = newStr.replace(/零(千|百|十)/g,'零').replace(/(零)+/g,'零').replace(/零(亿|万)/g,'$1');
return newStr;
}
console.log(fn('205402002103'));
4.考察闭包1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16var x = 20;
var a = {
x : 15,
fn : function(){
var x = 30;
return function(){
return this.x;
};
}
};
console.log(a.fn());
console.log((a.fn())());
console.log(a.fn()());
console.log(a.fn()() == (a.fn())());
console.log(a.fn().call(this));
console.log(a.fn().call(a));
先说一下输出的答案:
1)function(){return this.x;}
2)20
3)20
4)true
5)20
6)15
这道题中的this都是指向windows,所以this.x的值都为20,第1、2、3、4种情况都很好理解,到第五第六种考察了call这个函数,call的用途:
// 1. 替换函数运行环境中的this
// 2. 传递参数
// 3. 运行函数
所以第六种是把this指向了a对象,所以输出的是a.x就为15。
5.编写一个函数fn(Number n),将数字转为大写输出,如输入123,输出一百二十三1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18function fn(n){
if(!/^([1-9]\d*)/.test(n)){
return '非法数据';
}
var unit = '千百十亿千百十万千百十个';
if(n.length > unit.length){
return '数据过长';
}
var newStr = '';
var nlength = n.length;
unit = unit.substr(unit.length - nlength);
for(var i = 0; i < nlength; i++){
newStr += '零一二三四五六七八九'.charAt(n[i]) + unit.charAt(i);
}
newStr = newStr.substr(0,newStr.length-1);
newStr = newStr.replace(/零(千|百|十)/g,'零').replace(/(零)+/g,'零').replace(/零(亿|万)/g,'$1');
return newStr;
}
这题考察了正则表达式还有数组的操作。