我们接着昨天说,昨天大概说了一些数据类型和原型链以及继承的东西,今天继续说下面的东西。
7.作用域和闭包
说到js面试,三座大山肯定是一个面试官都会问到,三座大山指的是原型和原型链·作用域闭包·异步,这三个我们先说一下第二个----------作用域闭包
相关题目:
说一下变量提升的理解?
说明this的几个使用场景?
10个<a>点击弹出对应序号?
如何理解作用域?
实际开发中闭包的作用?
首先第一个,考察的是你对代码执行上下文的理解,执行上下文比如下面代码:
console.log(a);
var a=100;
上面代码第一行打印出来肯定是undifind,因为变量执行顺序没有在调用时候定义。在看下面代码:
fn("zhangsan");
function fn(name){
age=20;
console.log(name,age);
var age;
}
上面代码执行时候输出的是什么?答案是:zhangsan,20;
为什么上面执行顺序不行,而第二个就可以,答案很简单,就是浏览器在读代码的时候会对函数声明和变量定义读取时候不一样,我具体也说不清,大家可以上网查一下,有花说不出哎,口才不好。。。。。。
变量提升理解就是变量定义和函数声明(注意函数声明和函数表达式不一样)
this的相关问题
this用到的场景分为四种:
第一种:作为构造函数执行,代码如下:
function Foo(name){
this.name=name
}
var f=new Foo("zhangsan")
第二种:作为对象属性执行,代码如下:
var obj={
name="A";
printName:function(){
console.log(this.name)
}
}
obj.printName();//this就是obj
第三种:作为普通函数执行,代码如下:
function(){
console.log(this)
}
这个this就是指的是window
第四种:call,apply,bind,代码如下:
- function add(a,b)
- {
- alert(a+b);
- alert(this)\\这个this指的是第一个参数a
- }
- function sub(a,b)
- {
- alert(a-b);
- }
-
- add.call(sub,3,1);
这个例子中的意思就是用 add 来替换 sub,add.call(sub,3,1) == add(3,1) ,所以运行结果为:alert(4); // 注意:js 中的函数其实是对象,函数名是对 Function 对象的引用。
call方式实现继承:
function Animal(name){
this.name=name;
this.showName=function(){
alert(this.name);
}
}
function Cat(name){
Animal.call(this,name)
}
var cat=new Cat('black cat');
cat.showName();
Animal.call(this) 的意思就是使用 Animal对象代替this对象,那么 Cat中不就有Animal的所有属性和方法了吗,Cat对象就能够直接调用Animal的方法以及属性了.
apply和call的区别就是一个[]的区别 自己对比代码就好了:
function Animal(name) {
this.name=name;
this.showName=function (name) {
alert(this.name)
}
}
function Cat(name) {
Animal.apply(this,[name])
}
var cat=new Cat(this,'black cat')
cat.showName();
bind的区别就是可以链式操作
function Foo(name,age) {
console.log(this)//window
alert(name)//zhangsan
}
Foo.bind({y:200})
Foo("zhangsan",200);
作用域
作用域对于js来讲,js中没有块级的作用域,只有函数作用域和全局作用域
在js的变量中,只有函数可以改变它的作用域,函数内不能调用函数外的变量,除非是全局变量。有一个变量叫自由变量,自由变量就是当前作用域没有定义的变量叫做自由变量。if语句不可以改变作用域!!!
闭包
闭包不用纠结于这两个字,我个人觉得这个名字起的很蛋疼,好像很高大上一样,但是并没有。其实很简单,其实闭包的应用场景就是两种:
第一种:函数作为返回值的时候用到了闭包:
function F1() {
var a=100;
return function () {
alert(a)
}
}
var f1=F1();
var a=200;
f1();
上面 alert出来的值是100;
第二种:函数作为参数使用了闭包
function F1() {
var a=100;
return function () {
console.log(a);
}
}
var f1=F1();
function f2(fn) {
var a=200;
fn()
}
f2(f1)
console出来的是100
解题:创建10个<a>点击时弹出对应的序号
var i;
for (i=0;i<10;i++){
(function (i) {
var a=document.createElement("a");
a.innerHTML=i+'<br>';
a.addEventListener('click',function (e) {
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
})(i)
}
解体:实际应用中闭包的使用:获取用户第一次登陆执行事件(封装变量收敛权限)
function isFirst() {
var _list=[];
return function (id) {
if(_list.indexOf(id)>0){
return false;
}else {
_list.push(id)
return true//执行对应的事件
}
}
}
var firstLoad=isFirst();
firstLoad(10)>>>>>>>>>>>>>>true
firstLoad(10)>>>>>>>>>>>>>>false
上面主要原理就是在isFirstLoad()函数外面,根本不可能修改掉_list的值
8.异步和单线程
对应题目,同步和单线程的区别是什么?
举一个同步和异步的例子?
关于setTimeout笔试题?
前端使用异步的场景有哪些?
解答:
同步和异步最主要的区别就是有没有阻塞程序的发生!!!
什么时候需要用异步:有可能发生等待的时候需要使用异步。等待中不能像alert一样阻塞程序运行。什么时候要等待都需要用异步。
前端使用异步的场景:定时任务时候(1 定时任务 settimeout和setinterval。2 网络请求时候 ajax请求 动态<img>加载时候 3 事件绑定)
还有一点要说的是JavaScript语言是一种单线程语言,一次只能干一件事
9. 获取2017-11-11格式日期
Data构造函数。
function formData(dt) {
if(!dt){
var dt=new Date();
}
var year=dt.getFullYear();
var mouth=dt.getMonth()+1;
var day=dt.getDate();
if (mouth<10){
mouth='0'+mouth
}
if (day<10){
day="0"+day
}
return year+"-"+mouth+"-"+day
}
var dt=new Date();
var aaa= formData(dt);
console.log(aaa)
10 获取一个随机十位整数
var num=Math.random();
var num1=num+"0000000000";
var random=num1.slice(0,10);
console.log(random)
11 forEach every some sort map Filter这几个函数的用法和解释
var arr=[1,2,3];
arr.forEach(function (item,index) {
console.log(index,item)//index是元素 item是下标
})
var result=arr.every(function (item,index) {
if (item<4){
return true;//是不是所有的元素都满足小于4
}
})
var result=arr.some(function (item,index) {
if (item<2){
return true;//至少有一个满足小于2
}
})
var result=arr.sort(function (a,b) {
return a-b;//从小到大排序或者从大到小排序
})
var result=arr.map(function (item,index) {
return "<b>"+item+"</b>"//将元素重新组装并返回
})
var result=arr.filter(function (item,index) {
if (item>=2){//过滤元素
return true
}
})
12. attribute和prototy的区别
两者都是属性 而proerty值得属性是我们自己定义的属性指的是js对象的属性,而attr指的是我们html标签内的属性
还有一个就是关于冒泡事件的处理,阻止冒泡的话有一个方法就是 e.stopPropatation();可以阻止冒泡;
13.关于跨域的问题
我们用到最多的就是Jsonp
定义:浏览器有同源策略,不允许访问其他服务器地域接口;
条件:协议。域名。端口有一个不一样就算跨域了
有三个标签可以允许跨域{
<img src="*******">
<link href=********>
<script src="*****">
}
以上三个可以允许跨域请求,而jsonp用到的就是<script>
具体用法:
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$.ajax({
url:"http://crossdomain.com/services.php",
dataType:'jsonp',
data:'',
jsonp:'callback',
success:function(result) {
for(var i in result) {
alert(i+":"+result[i]);//循环输出a:1,b:2,etc.
}
},
timeout:3000
});
</script>
1
4. 手写原生ajax请求
var xhl=new XMLHttpRequest();
xhl.open("GET","/api",false);
xhl.onreadystatechange=function () {
if(xhl.readyState==4){
if (xhl.status==200){
alert(xhl.responseText)
}
}
}
xhl.send(null);
15.存储问题
描述cookie,sessionStrorage和localStrorage区别
首先说一下cookie,其实这个本来是为服务器服务用的,是客户端和服务端之间的通讯用的,但是因为它是有这个储存的功能,所以被临时借鉴过来。
用法只是通过document.cookie=******(字符串)直接获取和修改就可以了。缺点是只有4kb,太小。
后来H5只有就出来了两个专为前端设计的存储机制就是sessionStrorage和localStrorage;
他们两个的区别session是浏览器一关闭就没了,而local关闭浏览器还会有的!
sessionStrorags.setItem(item,value);
localStrorage.setItem(key);