JavaScript笔试知识点整理
JavaScript笔试知识点整理
2018.09.28
2018.09.29
2018.09.30
定义函数
在Javascript定义一个函数f有三种方式:第1种最常用,后两种都是把一个匿名函数复制给变量f
- 函数声明:
function
f(x){ alert(x); } - 函数表达式: var f =
function
(x){ alert(x); } - 构造函数: var f = new
Function
(‘x’, ‘alert(x);’)
var f = function g() {// 函数外部无法通过 g 访问到函数
return 23;
};
typeof g;// undefined
typeof f();// "number"
typeof g();// Error
函数执行完一次,若无return 返回值和声明变量接受返回值,都会立即消失成为undefined
output(typeof (function() {output(“Hello World!”)})());// Hello World! undefined
变量提前
函数声明可以被提前,但函数表达式不能被提前
(function() {
//var foo; 被提前的foo
var x=foo();
var foo=function foo() {//函数声明foo(等号左边)被提前
return “foobar”
};
return x;// foo未被定义为函数,报错
})();
this指向
this是在函数执行时被绑定的,它始终代表的是调用当前函数的那个对象。4种函数调用模式
- 方法调用
函数被保存为一个对象的属性时,称其为该对象的方法。方法被调用时,this被绑定到这个对象上。
var name = "window";
var obj_0 = {
name: "goozy",
sayName: function() { //函数作为对象的属性称为方法
console.log(this.name); // this绑定到obj_0
}
};
obj_0.sayName(); // goozy
var f = obj_0.sayName;
f();// window
- 函数调用
函数不是对象的属性时,那么它就是被当做函数调用。this被绑定为全局对象,浏览器环境下即
window
对象。
var name = "window";
function sayName() {
console.log(this.name);
}
sayName();
- 构造函数
函数加上
new
来调用,会创建一个连接到该函数prototype成员的新对象,同时,this会被绑定到这个新对象上。这个函数就称为此对象的构造函数。
function Obj_1() {
this.name = "goozy";
}
var person = new Obj_1();//Obj_1作为构造函数被调用,this被绑定为新创建的对象person
console.log(person.name); //goozy
- apply调用
所有函数对象的
apply
和call
方法可以让我们构建一个参数数组/列表传递给调用函数,也允许改变this的值。
var name = "window";
var person = {
name: "goozy"
};
function sayName() {
console.log(this.name);
}
sayName(); //window
sayName.apply(person); //goozy(apply模式调用sayName,传入第一个参数为person,this被绑定到person对象)
sayName.apply(); //window
- 练习
person2.sayName(); 这还是
方法调用
模式,对象为person2,sayName函数体最终执行
的函数是fun,fun是用函数调用
模式调用的。this绑定为window,结果为window。
var name = "window";
function showName() {
console.log(this.name);
}
var person1 = {
name: "goozy",
sayName: showName
}
var person2 = {
name: "Jake",
sayName: function() {
var fun = person1.sayName;
fun();
}
}
person1.sayName(); //goozy
person2.sayName(); //window
JSONP的优缺点
- 优点
- 不像XMLHttpRequest对象的Ajax请求那样受到同源策略的限制
-
兼容性更好
,在老版本浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持 - 请求完毕后可
调用callback回传
结果。
- 缺点
-
只支持GET
请求而不支持POST等其它类型的HTTP请求 - 只支持跨域HTTP请求,不能解决不同域的两个页面之间如何调用JavaScript的问题
-
运算符
1. 优先级
console.log('Value is ' + (val != '0') ? 'define' : 'undefine');//define
//+优先级大于?,所以('Value is ' + (val != '0')) ? 'define' : 'undefine'
if(! "a" in window){// !"a"先执行
var a = 1;
}
alert(a);
2.常见运算符
进行运算时,+号,数字 隐式转换成字符串。其余的运算符号是字符串隐式转换成数字。
类型转换
三元运算符先"分清是非","=="运算符比较"喜欢"Number"类型。
null与undefined在与其他数相等运算时不进行类型转换
console.log(([])?true:fasle);// => console.log((true)?true:false);
console.log([]==false?true:false); // => console.log(0==0?true:false);
console.log(({}==false)?true:false);//=>console.log((NaN==0)?true:false);
console.log(undefined == null);// true
console.log(undefined === null);// false
console.log(1+ +"2"+"2");// 1+2 +"2" => 32
console.log(1+ +"b"+"2");// NaN + "2" => NaN2
同步与异步
事件
(click,focus等等),定时器
(setTimeout和setInterval),ajax
,都是会触发异步
,js是单线程的,优先处理同步
任务;
常见异步:回调函数(callback)、事件监听(click,focus等等)、发布/订阅、Promise对象
var elements=document.getElementsByTagName('li');
var length=elements.length;
for(var i=0;i<length;i++){// for循环是同步任务,onclick是异步任务
elements[i].onclick=function(){// for循环执行完了,全局的变量i通过i++变成4了
alert(i);// 4 4 4 4
// 解决方式使用:let限制i;给匿名函数后面加()
}
}
回调时,被回调的函数会被放在event loop里,等待线程里的任务执行完后才执行event loop里的代码
function foo() {
console.log('first');
setTimeout(function(){
console.log('second');
},5);
}
for (var i = 0; i < 439; i++) {
foo();
}
// 首先全部输出first,然后全部输出second
Ajax工作原理
Ajax技术核心就是
XMLHttpRequest
对象。1.创建xhr对象=>2.发送请求(open,send)=>3.获取响应
- 创建对象:
var xhr = new XMLHttpRequest();
- xhr 发送请求
xhr.open('get','test.html','true');
xhr.send();
- xhr获取响应
xhr.onreadystatechange = function(){
if(xhr.readystate == 4){//请求的状态码
/*
0:请求还没有建立(open执行前)
1:请求建立了还没发送(执行了open)
2:请求正式发送(执行了send)
3:请求已受理,有部分数据可以用,但还没有处理完成
4:请求完全处理完成
*/
alert(xhr.responseText);//返回的数据
}
}
Ajax和Flash
Ajax的优缺点
- 优点
- 可搜索性
- 开放性
- 费用
- 易用性
- 易于开发。
- 缺点
- 可能破坏浏览器的后退功能
- 使用动态页面更新使得用户难于将某个特定的状态保存到收藏夹中
Flash的优缺点
- 优点
- 多媒体处理
- 兼容性
- 矢量图形
- 客户端资源调度
-缺点 - 二进制格式
- 格式私有
- flash文件经常会很大,用户第一次使用的时候需要忍耐较长的等待时间
- 性能问题
前端性能指标
分页面、区域、浏览器、性能指标,以下主要是页面的性能指标
前端性能
-
白屏时间(first Paint Time)——用户从打开页面开始到页面开始有东西呈现为止
-
首屏时间——用户浏览器首屏内所有内容都呈现出来所花费的时间
-
用户可操作时间(dom Interactive)——用户可以进行正常的点击、输入等操作,默认可以统计domready时间,因为通常会在这时候绑定事件操作
-
总下载时间——页面所有资源都加载完成并呈现出来所花的时间,即页面 onload 的时间
Promise
一个promise可能有三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected)
一个promise的状态只可能从“等待”转到“完成”态或者“拒绝”态,不能逆向转换,同时“完成”态和“拒绝”态不能相互转换.
JavaScript Promise 启示录
同步与异步-思否
易错题
- 变量
var x = 10;
var a,b;
(function(){
alert(a);// undefined
alert(b);// undefined
var a=b=3;//相当于局部变量var a = 3;全局变量b = 3;
alert(a);// 3
alert(b);// 3
alert(x)// 10
})();
alert(a);// undefined
alert(b);// 3
- 原型继承
js 的继承靠的是
__proto__
,并不是prototype
var F=function(){};
Object.prototype.a=function(){};// (F.prototype)[的构造函数] === Object
Function.prototype .b=function(){};// F[的构造函数] === Function
var f=new F();// f可以取到a,不能取到b
-
f.
__proto__
=== f[的构造函数].prototype === F.prototype -
F.prototype.
__proto__
=== (F.prototype)[的构造函数].prototype === Object.prototype (所以a能够 通过f.a访问) -
f.constructor === F
-
F.
__proto__
=== F[的构造函数].prototype === Function.prototype (所以b可以通过, f.constructor.b访问到) -
闭包
test构成了一个
闭包
,r1跟r2各自有自己的test作用域
JavaScript闭包-阮一峰
function test(){
var n = 4399;
function add() {// 闭包
n++;
console.log(n);
}
return {
n: n,
add: add
}
}
var r1 = test();
var r2 = test();
r1.add();// 4400
r1.add();// 4401
console.log(r1.n)// 4399
r2.add();// 4400
- 局部变量和参数传递
var bb = 1;
var cc = 1;
function aa(bb) {
bb = 2;//这里的bb赋值给了函数aa的参数bb,不影响全局的bb
alert(bb);
};
function dd() {
cc = 2;
alert(cc);
};
aa(bb);// 2
alert(bb);// 1
dd();// 2
alert(cc);// 2
var foo = {n:1};
(function(foo){ //形参foo同实参foo一样指向同一片内存空间,这个空间里的n的值为1
var foo; //优先级低于形参,无效。
console.log(foo.n); //输出1
foo.n = 3; //形参与实参foo指向的内存空间里的n的值被改为3
foo = {n:2}; //形参foo指向了新的内存空间,里面n的值为2.
console.log(foo.n); //输出新的内存空间的n的值
})(foo);
console.log(foo.n); //实参foo的指向还是原来的内存空间,里面的n的值为3.
- 同名函数
同名的函数后者会覆盖前者
var m= 1, j = k = 0;
function add(n) { // 前
return n = n+1;
}
y = add(m);// 应用后者的add(),4
function add(n) { // 后
return n = n + 3;
}
z = add(m); // 4
- 数组的长度
arr.length
是对arr对象的length属性进行一个访问
var arr = [];
arr[0] = 0;
arr[1] = 1;
arr.foo = 'c';// 为arr对象创建一个属性,不在length属性范畴
console.log(arr.length);// 2
RegExp对象的3个方法
-
test():检测一个字符串是否匹配某个正则表达式,如果匹配成功,返回true,否则返回false;
-
exec():检索字符串中与正则表达式匹配的值,返回一个数组,存放匹配的结果;如果未找到,返回null;
-
compile():可以在脚本执行过程中编译正则表达式,也可以改变已有表达式。
Number转换
console.log(Number("")); //0
console.log(Number(null)); //0
console.log(Number(undefined)); //NaN
console.log(parseInt("")); //NaN
console.log(parseInt(null)); //NaN
console.log(parseInt(undefined)); //NaN
DNS域名系统
将域名解析成IP地址
- 域名必对应一个ip地址,而ip地址不一定有域名
- DNS主要是UDP协议,但是当请求字节过长超过512字节时,是用TCP协议,它可以分割成多个片段
- 默认端口号是53
- 浏览器的DNS缓存:chrome对每个域名会默认缓存60s;IE将DNS缓存30min;Firefox默认缓存时间只有1分钟;Safari约为10S
判断一个对象是否为Array
typeof(arr);// 返回的是 Object而不是Array
arr instanceof Array;// true,但跨 frame 对象构建的场景下会失效
Object.prototype.toString.call(arr) === '[object Array]';// 最正确的判断方式
作用域
JavaScript的跨域
只要 协议 、 域名 、 端口 有任何一个 不同, 都被当作是 不同 的域
- 修改document.domain来跨子域
- 使用window.name来进行跨域
- js可以使用jsonp进行跨域
sessionStorage 、localStorage 和 cookie 之间的区别
-
共同点
- 都保存在浏览器端,且同源
-
区别
1.cookie
在浏览器和服务器间来回传递
。而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。
2. 存储大小限制也不同,cookie数据不能超过4k,只适合保存很小的数据,如会话标识。sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
3. 数据有效期不同,sessionStorage
:仅在当前浏览器窗口关闭前有效
,自然也就不可能持久保持;localStorage
:始终有效
,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie只在设置的cookie过期时间之前
一直有效,即使窗口或浏览器关闭。
4. 作用域不同,sessionStorage不在不同的浏览器窗口敏感词享,即使是同一个页面;localStorage在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的。
5. Web Storage支持事件通知机制,可以将数据更新的通知发送给监听者。
6. Web Storage 的 api 接口使用更方便。
GET和POST的区别
- GET请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间以&amp;相连,提交的数据不大于1024字节
- POST把提交的数据则放置在是HTTP包的包体中,POST没有限制,可传较大量的数据
- 在ASP中,服务端获取GET请求参数用Request.QueryString,获取POST请求参数用Request.Form
- POST的安全性要比GET的安全性高
Object属性判断
-
hasOwnProperty
: 是用来判断一个对象是否有你给出名称的属性或对象。此方法无法检查该对象的原型链中是否具有该属性,该属性必须是对象本身
的一个成员。 -
isPrototypeOf
: 是用来判断要检查其原型链
的对象是否存在于指定对象实例中,是则返回true,否则返回false。
函数原型重写
重写原型对象切断了现有原型与任何之前
已经存在的实例之间的联系,他们引用的仍然是最初的原型
只有实例对象上不存在的属性和方法才会去原型上查找
- 重写原型后实例化
function Person(){}
Person.prototype = {
name :"goozy",
add :function(){
alert(this.name);
},
}
var p2 =new Person();//实例化
p2.add();//goozy
- 先实例化再重写原型
function Person(){}
var p2 =new Person();//实例化
Person.prototype = {// 切断与实例p2的联系
name :"goozy",
add :function(){
alert(this.name);
},
}
p2.add();//error:p2.add is not a function
- 练习
function A() {
this.do=function() {return 'foo';};
}
A.prototype=function() {
this.do=function() {return 'bar'};
};
var x=new A().do();
console.log(x);// foo
变量回收
-
全局变量不会被回收。
-
局部变量会被回收,也就是函数一旦运行完以后,函数内部的东西都会被销毁。
-
只要被另外一个作用域所引用就不会被回收
var i = 1;
var i = 2;// 第二个全局i覆盖前一个 =>1
var add = function() {// 全局的add
var i = 0;
return function()
{
i++;// 闭包作用域链中的i
console.log(i);
}
}();
add();
//3个变量未回收
i++ 与 ++i 的主要区别
- i++ 返回原来的值,++i 返回加1后的值。
- i++ 不能作为左值,而++i 可以。
var x=0;
switch(++x)
{
case 0: ++x;
case 1: ++x;
case 2: ++x;
}
console.log(x);//3
//没有break,会一直执行
杂七杂八
零散的知识点
- call, apply方法第一个参数,即执行时上下文对象相同,call传递一个参数列表,而apply则传递一个参数数组。
- concat返回原数组的一个
副本
,不会改变现有的数组
- 域名不同不能使用ajax
- 基本类型变量(num, string, boolean, null, undefined)用
八字节
内存,引用类型变量(对象、数组和函数)则只保存值的引用(即内存地址) - img标签若src无指定地址,将触发onerror事件
- 所有对象都有
__proto__
,所有函数对象都有prototype
- isNaN()在接受一个值后,会尝试将这个值转换为数值。任何
不能被转换为数值
的值都会导致这个函数返回true。 -
typeof
返回的是string - 对象和数组里的for-in,对象里用来枚举对象的属性,数组里用来枚举数组索引。
- js代码写在标签,会导致页面在加载的时候自身被执行
-
function*声明
(function关键字后跟一个星号)定义了一个 生成器函数(generator function),它返回一个Generator对象
。 - javascript的事件模型:事件捕获->事件处理->事件冒泡
- 删除arr数组中的第i个元素:arr.splice(i-1,1)
- JS里判断一个对象oStringObject是否为String:不能用
typeof oStringObject == 'string'
,由于已经说是对象所以typeof会返回Object -
void();
会返回SyntaxError