前端面试题准备 2

写博客真是一个好事情,自已花了一天弄了这篇,加深了很多印象。可以时不时复习一下,也希望能够帮助到他人。

一、HTML5的语义化标签:大概有<header><nav><article><section><aside><footer>,比<div class="">更直观,也方便搜索引擎。

二、正则,这是一大块,项目中也常用到。(有时用js有时用C#,虽然规则是一样的,但命令常搞混)

(资料参考:http://blog.csdn.net/zaifendou/article/details/5746988

http://www.blogjava.net/onejavaer/articles/79070.html

http://www.jb51.net/article/25313.htm)

1、exec()

var regx=/a(d+)(A)c/;
var result = regx.exec("a123Acddd");
result

result是["a123Ac","123","A"] ,其中第一个是匹配到的值,后面两个是括号里的值。

但console.log(result)却是 ["a123Ac", "123", "A", index: 0, input: "a123Acddd"],有时调试时要注意,不要搞混了

var regx=/ad+c/;
var result=regx.exec("a123cddd");

没有括号,result是["a123c"]

var regx=/userd/g;
var rs=regx.exec("ddduser1dsfuser2dd");
var rs1=regx.exec("ddduser1dsfuser2dd");
console.log(rs);
console.log(rs1);

得到rs1是["user1"],rs2是["user2"]。。。这是个坑,以前都没注意到。

不符合条件的话,是返回null

2、test()

var regx=/userd+/g;
var flag=regx.test("user12dd");
console.log(flag);

得到true,其实用其它方法不符合时就会返回null,就可以判断了,一般都不用专门test()来判断

============以上两个是regx的方法,后面的是string的方法,常弄混==============

 3、match()

var regx=/userd/g;
var str="user13userddduser345";
var rs=str.match(regx);
console.log(rs)

显示 ["user1", "user3"],这会又没后面那个什么Index,Input了。。。不知为何exec在console.log时会附带那些东西。

regx加了/g,是显示全部,不加/g是第一个,如果不匹配,是返回null。

4、search()

var regx=/userd/g;
var str="ABCuser13userddduser345";
var rs=str.search(regx);

rs是3,如果不符合条件,得到-1。

和indexOf()非常类似

var regx=/userd/g;
var str="ABCuser13userddduser345";
str.indexOf("user");

得到的也是3,查不到也是-1。但indexOf()只能查具体的字符串,不能查正则。

 5、replace(expr,str)

var regx=/user/g
var str="user13userddduser345";
var rs=str.replace(regx,"ABC");

得到rs是"ABC13ABCdddABC345"

如果不加/g,或直接是字符串"user",则仅替换第一个

var regx=/user/    //或var regx="user"
var str="user13userddduser345";
var rs=str.replace(regx,"ABC");

得到的都是 "ABC13userddduser345"

6、split(expr)

不管是否加/g,或直接是字符串,效果都是一样的。这点和replace有所不同,也是个坑

var regx=/user/g;    //或 var regx="user"
var str="user13userddduser345";
var rs=str.split(regx);

得到的都是 ["", "13", "ddd", "345"]

7、转义

需要转义的有    * . ? + $ ^ [ ] ( ) { } | / 

8、预定义

.     IE下[^ ],其它[^ ] 匹配除换行符之外的任何一个字符 
d     [0-9] 匹配数字 
D     [^0-9] 匹配非数字字符 
s     [ fx0B] 匹配一个空白字符 
S     [^ fx0B] 匹配一个非空白字符 
w     [a-zA-Z0-9_] 匹配字母数字和下划线 
W     [^a-zA-Z0-9_] 匹配除字母数字下划线之外的字符 

9、/g是全局,/i是忽略大小写,/m是多行查找。

另有RegExp.$n (n为1~99),表示第几个匹配项

var r = /(d+)-(w+)/;
var b=r.exec("1234-abcd-b");
console.log(RegExp.$1+"~"+RegExp.$2);

b = r.test("1234-abcd");
console.log(RegExp.$1+"~"+RegExp.$2);

得到的均为  1234~abcd

10、匹配方式

*是零次或多次,+是一次或多次,?是零次或一次,而且在量词后面加?就变成惰性模式,即匹配尽量少(默认是贪婪模式,即匹配尽量多)。

var str = "abc"; 
var re = /w+/; //将匹配abc
var result = re.exec(str)
console.log(result)

re = /w+?/;//将匹配a
result = re.exec(str)
console.log(result)

基本上就这些,其它高级用法一时也没法列全,在项目中可以边试边用,面试时这些应该就差不多了。

三、原型,扩展原型方法,项目中有用过String.Format(),就是像C#的string.Format("xxx{0}",str)一样用法。

if (!String.prototype.format) {
    String.prototype.format = function () {
        var args = arguments;
        return this.replace(/{(d+)}/g, function (match, number) {
            return typeof args[number] != 'undefined' ? args[number] : match;
        });
    };
}

 

四、阻止冒泡:preventDefault(阻止事件默认行为)、stopPropagation(阻止冒泡)、return false(相当于前面两个都执行)。

五、兼容

var e = window.event || evt;
var tag = e.target || e.srcElement;
var keyCode = evt.keyCode || evt.which;

判断浏览器(顺序不能错)就记住关键词window.navigator.userAgent,然后顺序IE、火狐、谷歌、欧朋、苹果

function getExplorer() {
    var explorer = window.navigator.userAgent ;
    if (explorer.indexOf("MSIE") != -1) {
        console.log("ie");
    }
    else if (explorer.indexOf("Firefox") != -1) {
        console.log("Firefox");
    }
    else if(explorer.indexOf("Chrome") != -1){
        console.log("Chrome");
    }
    else if(explorer.indexOf("Opera") != -1){
        console.log("Opera");
    }
    else if(explorer.indexOf("Safari") != -1){
        console.log("Safari");
    }
}

六、作用域(配合this、闭包),经常有坑,一般是function声明会提到最前,且function内部有定义变量的,就不会再去找上一级,但是定义的变量又未执行到,还是undefined

http://mianshiti.diandian.com/post/2013-04-05/40048538140这一题比较有代表性

var foo = 'hello';
(function() {
  var foo = foo || 'world';
  console.log(foo);
})();
//显示world

var foo = 'hello';
(function() {
  console.log(foo);
  var foo = foo || 'world';
})();
//显示undefined

var foo = 'hello';
(function(f) {
  var foo = f || 'world';
  console.log(foo);
})(foo);
//显示hello
var i=9;
function fo(){
    var i=0;
    return function(n){
        return n+(++i);
    }
};
var f=fo();

var a = f(15);console.log(a)
var b = fo()(15); console.log(b)
var c = fo()(20); console.log(c)
var d = f(20);console.log(d)

分别得到16 16 21 22

 珠峰有一题比较复杂  http://www.iqiyi.com/w_19rr1au1fh.html

var number=2;
var obj={
    number:4,
    fn1:(function(){
        this.number *= 2;
        number=number*2;
        var number=3;
        return function(){
            this.number *= 2;
            number *= 3;
            console.log("inside:"+number);
        }
    })(),
    db2:function(){this.number *= 2}
};
console.log("Only Define,number is:"+number);
var fn1=obj.fn1;
console.log("After Assign,number is:"+number);
console.log("Run fn1():");
fn1();
console.log("After Run fn1(),number is:"+number);
console.log("Run obj.fn1():");
obj.fn1();
console.log("After Run obj.fn1(),number is:"+number);
console.log("window.number is:"+window.number);
console.log("obj.number is:"+obj.number)

Only Define,number is:4  //在定义中,fn1的方法是立即执行的(function(){})(),里面的this.number,是执行时的window,所以window.number*2 = 4
After Assign,number is:4  //赋值只是引用对象一下,不改变什么
Run fn1():
inside:9  //fn1() ->obj.fn1() ->执行闭包里面的函数,里面的number就是上一级的 var number = 3,所以最后是3*3==9
After Run fn1(),number is:8  //这时的window.number,在一开始已经变成4了,再执行一次,又*2,变成8了
Run obj.fn1():
27  //和前面的fn1()是一样的,相当于再执行一次,而闭包不释放,上次又经是9了,再*3=27
After Run obj.fn1(),number is:8
window.number is:8
obj.number is:8

有些难搞懂,要配合下面这个再测一下 ,为了不混淆,把各参数都改成质数,虽然数字看着有些大,但能弄清问题实际

var number=3;
var obj={
    number:5,
    fn1:(function(){
        this.number *= 7; console.log("this.number *= 7,this.number="+this.number);console.log(this)
        number=number*11; console.log("number=number*11;,number="+number);
        var number=13;
        return function(){
            this.number *= 17; console.log("this.number *= 17,this.number="+this.number); console.log(this)
            number *= 19; console.log("number *= 19,number="+number);
            console.log("inside:"+number);
        }
    })(),
    db2:function(){this.number *= 23;  console.log("this.number *= 23,this.number="+this.number);}
};
console.log("var fn1=obj.fn1;");
var fn1=obj.fn1;
console.log("obj.fn1();")
obj.fn1();
console.log("obj.fn1() 1times, number is:"+number);
console.log("obj.fn1() 1times, obj.number is:"+obj.number);
obj.fn1();
console.log("obj.fn1() 2times, number is:"+number);
console.log("obj.fn1() 2times, obj.number is:"+obj.number);
obj.fn1();
console.log("obj.fn1() 3times, number is:"+number);
console.log("obj.fn1() 3times, obj.number is:"+obj.number);
fn1();
console.log("fn1() 1times, number is:"+number);
console.log("fn1() 1times, obj.number is:"+obj.number);
fn1();
console.log("fn1() 2times, number is:"+number);
console.log("fn1() 2times, obj.number is:"+obj.number);
fn1();
console.log("fn1() 3times, number is:"+number);
console.log("fn1() 3times, obj.number is:"+obj.number);

this.number *= 7,this.number=21
Window {top: Window, location: Location, document: document, window: Window, external: Object…}
number=number*11;,number=NaN

此时是仅定义时输出的。因为是(function(){})()这种直接执行的形式,所以定义时就执行了。以后都是执行return里面的返回值。

此时的this指向window,把全局的number变成3*7=21了。而number=number*11,此时的number在fn1中有定义var number=13,但未执行到,所以此时还是undefined(这是个坑)

===================

var fn1=obj.fn1; //仅是引用赋值,未引发输出


obj.fn1();  //执行obj.fn1()
this.number *= 17,this.number=85
Object {number: 85}db2: ()fn1: ()number: 24565__proto__: Object
number *= 19,number=247
inside:247

此时的this指向obj,obj.number=5,所以obj.number ->5*17=85。

而number会去找上下文,发现obj.fn1有定义var number=13,所以number*=19   ->  13*19=247


obj.fn1() 1times, number is:21
obj.fn1() 1times, obj.number is:85

所以此时输出全局number是21,obj.number是85

===================

//第二次执行
this.number *= 17,this.number=1445
Object {number: 1445}
number *= 19,number=4693
inside:4693

同理this依然指向obj,而上一次obj.number已经变成85了,所以此次85*17=1445

number继续是obj.fn1.number,所以number  -> 247*19=4693
obj.fn1() 2times, number is:21
obj.fn1() 2times, obj.number is:1445

全局number=21一直没变

//第三次执行,和前两次一样分析即可
this.number *= 17,this.number=24565
Object {number: 24565}
number *= 19,number=89167
inside:89167
obj.fn1() 3times, number is:21
obj.fn1() 3times, obj.number is:24565

//第一次执行fn1()
this.number *= 17,this.number=357
Window {top: Window, location: Location, document: document, window: Window, external: Object…}
number *= 19,number=1694173
inside:1694173

this指向了window,这也是个坑。所以window.number  ->21*17=357,而obj.number就不会再变化了。
fn1() 1times, number is:357
fn1() 1times, obj.number is:24565

//第二次执行fn1()
this.number *= 17,this.number=6069
Window {top: Window, location: Location, document: document, window: Window, external: Object…}
number *= 19,number=32189287
inside:32189287

主要就是this指向了window,现在this.number就是window.number。而内部的number一直是*19
fn1() 2times, number is:6069
fn1() 2times, obj.number is:24565

//第三次执行fn1(),和前两次一样分析即可
this.number *= 17,this.number=103173
Window {top: Window, location: Location, document: document, window: Window, external: Object…}
number *= 19,number=611596453
inside:611596453
fn1() 3times, number is:103173
fn1() 3times, obj.number is:24565

这题比较绕,能搞清楚的话,就把闭包、作用域之类的全搞懂了,关键是fn1()指向了window。也不知道我理解的对不对,暂时先这样吧。

 

七、符号在html中表现

<    &lt;

>    &gt;

&    &amp;

"    &quot;

空格    &nbsp;

八、js异步加载(而不是在页头直接引用,增加页面载入速度)

function loadScript(url,callback){
    var script=document.creatElement("script");
    script.type="text/javascript";
    if(script.readyState){
        script.onreadystatechange=function(){
            if(script.readyState=="loaded"||script.readyState=="complete"){
                script.onreadystatechange=null;
                callback();
            }
        }
    }else{
        script.onload=function(){
            callback();
        }
    }
    script.src=url;
    document.getElementsByName("head")[0].appendChild(script);
}
    1.直接document.write");
        <script>
        document.write("<script src="test.js"></script>");
        </script>

     2.动态改变已有script的src属性
        <script src="" id="s1"><script>
        <script>
        s1.src="test.js"
        </script>
     3.动态创建script元素
        <script>
        var oHead=document.getElementsByTagName("HEAD").item(0);
        var oScript=document.createElement("script");
        oScript.type="text/javascript";
        oScript.src="test.js";
        oHead.appendChild(oScript);
       </script>

 

原文地址:https://www.cnblogs.com/liuyouying/p/5023308.html