1 变量声明提升的问题
大致的题目意思是这样的
var name = "haha"; function test() { console.log(name);//undefined var name = "test"; console.log(name);//test } test();
其实这个点是知道的 感觉容易是个坑 所以写出来(反正自己是入坑了)
我当时的第一个想法是函数内部能访问函数外部的全局变量 直接第一个log出haha 面试官估计黑了
原理
javascript允许在函数的任意地方声明多个变量,无论是在哪里进行声明,都等同于在顶部进行声明,所以上面的代码可以理解为下面的形式
var name = "haha"; function test() { var name; //var name = undefined; console.log(name);//undefined name = "test"; console.log(name);//test } test();
2 为ul的li绑定onclick事件,事件触发时log每个li的出现顺序
<ul> <li></li> <li></li> <li></li> </ul>
第一个li输出0 第二个1 第三个2
这次面试的经历有点脸红 哈哈 我信誓旦旦的跟面试官说这个问题我会,还说前两天写过 ,还加了个addLoadEvent()函数(在window.onlaod之后执行,形成队列) ,还好我回来自己试着敲了敲,脸红。。 我写的完全不对
这是我那次面试写的代码
function test() { var lis = document.getElementsByTagName("li"), len = lis.length; for(var i = 0;i < len;i++) { lis[i].onclick = function(event) { console.log(i); }; } }
结果是每次单击输出的都是3
我是这样理解这个问题的 绑定的匿名函数存在对外部变量的访问,当函数触发的时候就会在作用链域去查找相应的值(i),javascript还存在这样的一个特性 没有局部作用域
for(var b = 0;b < 100;b++) { } console.log(b);//100
所以当触发的时候,访问的i的值是循环后的i的值 全是3 所以要使用闭包,保存当时循环时的i的值
function test() { var lis = document.getElementsByTagName("li"), len = lis.length; for(var i = 0;i < len;i++) { lis[i].onclick = (function(j){ return function() { console.log(j); } })(i); } } window.onload = test;
这里利用闭包实现了功能,传入了循环时的i值
3new Function()的问题 刚看到eval是魔鬼就想起这个问题了 当时完全的不了解new Function()这个用法 所以这个问题面试官一直摇头
大致的题目是new Function()与一个全局变量结合的问题 题目真心有点忘记了
解释先new Function()的用法吧 对比下eval(参考了javascript模式)
new Function()中的代码是在一个局部的函数空间中运行,因此代码中采取var 声明的变量不会自动成为全局变量
在eval中只有将eval调用封装在一个即时的函数中,才能保证不自动成为全局变量
var str1 = "var a = 1;console.log(a)"; eval(str1); var str2 = "var b = 2;console.log(b)"; new Function(str2)(); var str3 = "var c = 3;console.log(c)"; (function(){ eval(str3); }()); console.log(a);//1 console.log(b);//undefined console.log(c);//undefined
new Function在执行的过程中更像一个沙盒,它只能看见全局作用域
(function(){ var local = 1; new Function("console.log(local)")();//undefined })();
4 构造函数的 加new 和 不加new的使用对比
function test() { this.name = 'haha'; //默认返回this } var a = new test(); console.log(a.name); //haha var b = test(); console.log(b);//undefined console.log(window.name);//haha
这个问题是跟第一个那次面试一起遇到的应该 当时不知道这个点
当new test()的时候内部的this指向新生成的对象,并且对this进行操作,默认返回this 赋值给外部
当不用new 的时候 ,this指向全局对象,也就是在全局对象上添加属性 所以结果如上
5 最近的一次面试问了许多CSS的问题 感觉自己都没了解过 刚又看了一个牛人的博客的分享 感觉应该静下心慢慢的成长 别太浮躁了 分享出最近这次面试的感悟
6 这次问到的问题是块级元素和内联元素的问题 回答的很不像话
块级元素与内联元素
每一个网页元素都有一个display属性 像DIV这种display属性的默认值是block 也就是块级的元素 像span这样的元素 display属性的默认值是inline 块级元素会自动的占据一定的矩形空间而内联的元素则不会自动的占据一定的矩形空间,它们是依附于其他块级元素存在的 它们之间的差异是块级元素默认的占据一行 内联元素只能放在行内,不会造成前后的换行
可变元素 通过上下文的语境判断是块级元素还是内联元素
通过CSS的控制我们现在可以在改变块级元素和内联元素的display属性来达到我们布局的目的
7 这是一次面试考官根本没问我问题 直接给我留了一个作业 当时自己动手能力和独立思考的能力不强 根本想不到怎么去解决这个问题 我把这个问题贴出来 并且给出大致的实现思路
根据文本框输入的内容 动态的显示表格的内容(filter)
用到了jquery
<div> <input type="text" id="filterName" /> </div> <table> <thead> <tr><th>姓名</th><th>性别</th><th>暂住地</th></tr> </thead> <tbody> <tr><td>张山</td><td>男</td><td>北京</td></tr> <tr><td>李四</td><td>男</td><td>北京</td></tr> <tr><td>王五</td><td>男</td><td>长春</td></tr> <tr><td>小红</td><td>女</td><td>北京</td></tr> <tr><td>小路</td><td>女</td><td>长沙</td></tr> <tr><td>哈哈</td><td>男</td><td>韩国</td></tr> </tbody> </table>
首先有这样的一个页面的结构 我们可以在文本框上绑定keyup事件 获取它里面的内容 在通过jquery的contains选择器来达到选择的目的 进行元素的隐藏和显示
$("#filterName").keyup(function(){ $("table tbody tr").hide(); if($(this).val() == "") { $("table tbody tr").show(); } else { $("table tbody tr").filter(":contains('"+ $(this).val() +"')").show(); } });
8 关于call apply设置this的问题
call传递的参数是以一个一个方式传递的 a.call(b,var1,var2,var3) apply传递的是数组 a.call(b,[var1,var2,var3])
9 这个是我看到的一个知识点 关于参数的传递问题
var object = { name:"haha" } var num = 10; ;!function(obj) { obj.name = "aa"; }(object); //;是为了取消前面没有加;对后面的影响 !是形成一个立即调用的函数表达式 这里传入的是一个object 是引用类型 修改的时候会修改原来的对象 console.log(object.name); //aa ;!function(temp) { temp = 200; }(num); console.log(num); // 10 进行值传递的时候 不会修改原来的值
10 原型属性 遇到的一个自己没关注的点 分享出来
var Car = function(wheelcount) { this.wheels = wheelcount || 4; } Car.prototype.drive = function(miles){ this.odometer += miles; return this.odometer; } Car.prototype.odometer = 100; //对象的构造函数的原型上有一个方法和一个属性 var car = new Car(); console.log(car.drive(10)); //110 此时新创建的对象上并没有odometer属性 通过原型链查找到构造函数的原型上的odometer属性 进行操作 返回110 this指向的对象,也就在对象上生成了odometer属性 Car.prototype.odometer = 2000; //修改了构造函数原型上的odometer属性 console.log(car.drive(10)); //120 此时直接访问对象上的odometer属性 输出120
双重非的用法
!可以将undefined转换成true 所以我们就可以通过!!变量名 来判断一个变量名是否被定义
var person = { isEat:function() { return !!this.food; } } console.log(person.isEat()); //此时没有定义food属性 返回false person.food = 100; console.log(person.isEat()); //设置了food属性 显示true