zoukankan      html  css  js  c++  java
  • JavaScript -- BATweb笔试面试

     

    (1)JavaScript包括哪些数据类型?
    1.未定义(undefined) 2.空(null) 3.布尔(boolean) 4.字符串(string)
    5.数字(number) 6.对象(object)
    7.引用(reference) 8.列表(list) 9.完成(completion)
    reference,list,completion这3种类型是做为JavaScript运行时中间结果的数据类型 在代码中不能使用。

    (2)border-color-left、marin-left、-moz-viewport改写成JavaScript
    borderColorLeft,marinLeft, MozViewport,
    -moz-border-radius确实是写成MozBorderRadius.

    (3)请简述javascript延迟加载的方式?
    (1)将js脚本放在</body>之前,这样就可以在页面都显示之后,在继续加载.
    (2)使用script标签的defer和async属性,defer属性为延迟加载,是在页面渲染完成之后再进行加载的,

    而async属性则是和文档并行加载,这两种解决方案都不完美,原因在于不是所有浏览器都支持.async(异步).
    (3)监听onload事件,动态加载.

    	var script = document.createElement ("script");
    	script.type = "text/javascript";	  //Firefox, Opera, Chrome, Safari 3+
    	script.onload = function(){    
    	  alert("Script loaded!");};           //Internet Explorer 
    	  script.onreadystatechange = function(){      
    		if (script.readyState == "loaded" || script.readyState == "complete")
    	     	{            
    	     		script.onreadystatechange = null;            
    	     		alert("Script loaded.");      
    	     	} 
    	   }; 
    	script.src = "script.js"; 
    	document.getElementsByTagName("head")[0].appendChild(script);
    

    (4)通过ajax下载js脚本,动态添加script节点.
    这种方式与第二种类似,区别就在与js脚本的自动下载还是通过ajax下载,ajax的方式显然可控制性更好一点,它可以先下载js文件,但不立即执行:

    var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP');
    xhr.open("get", "script.js", true); 
    xhr.onreadystatechange = function() {     
      if (xhr.readyState == 4) {         
        if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304)
          {             
        	  var script = document.createElement ("script");             
        	  script.type = "text/javascript";             
        	  script.text = xhr.responseText;             
        	  document.body.appendChild(script);         
        	}     
        } 
    }; 
    xhr.send(null);

    (5)使用js函数setTimeout()延迟执行

    <script language="JavaScript" src="" id="my"></script> 
    
    <script> 
    	//延时3秒 
    	setTimeout(function () {
    		document.getElementById('my').src='script.css'; 
    	},3000);
    </script> 
    

     

    (5)看x, y, z的结果? //1 4 4

    <script type="text/javascript"> 
                var x=1,y=z=0;
                function add(n) {
              alert(‘one’);
                    return n=n+1;
                }     
                y=add(x);
    
           //y = 4,执行这段代码的时候,函数已经被替换了 alert( " y = " + y);
           //这个函数被重定义了.代替了之前的函数. function add(n) {           alert(‘two); return n=n+3; }
    z=add(x); alert(x + " " + y + " " + z ); //1 4 4
    </script>


      两次执行的都是弹出two.证明执行的都是第二个声明函数,
    证明函数执行之前,就已经完成替换了. 由于js是一个弱类型语言,不存在函数重载。重名函数就覆盖替换。

    因为无法判读int 或者是多参数问题。所以函数只能用名字判断。作为唯一标识。


      变量的定义是在所有代码执行的之前,在一个作用域内最先被预留在内存中的,这个变量占用了内存的存储位置,但还没有被定义(undefined),

    只有在遇到定义变量的语句的时候,才被赋值(defined)。程序的执行在变量存储之后按顺序进行的,在执行第一句alert的时候,变量没有被赋值,所以弹出undefined。

    (6)试从域名解析原理的角度简单分析,域名劫持是怎么发生的?有什么危害?

    域名就是DNS,用户IP记不住就记域名,www.baidu.com就是一个域名.电脑会把域名翻译成IP地址..
    域名的结构:是树形,分割是点 . 比如 以网易的域名为例:
    3g.163.com 的上级域名是 .163.com
    163.com 的上级域名是 .com
    这里的 .com 就被称为顶级域名(Top-Level Domain,简称 TLD)
    解析原理:当你在浏览器的地址栏中输入 www.163.com,然后敲回车,这时候电脑软件会进行如下一系列事情。
    1. 首先根据输入的网址,提取出域名。
    2. 如果你在系统中配置了 Hosts 文件,那么电脑会先查询 Hosts 文件,看这个www.163.com 否已经在 Hosts 里面有了对应的记录。如果有,直接就可以拿到该记录中的 IP地址,过程就结束了。
    3. 如果 Hosts 里面没有这个别名,那么电脑会看你有没有设置域名服务器(DNS 服务器)。如果你的系统没有设置域名服务器,那电脑就没辙了,浏览器直接会报错,说网站的域名无法解析。过程就结束了。
    4. 如果你设置过“域名服务器”,那么电脑会向这个域名服务器发送一个域名查询(DNS query)的请求,然后等候域名服务器的回应。
    5. 如果域名服务器始终没有回应(比如域名服务器挂了,或域名服务器的IP填错了,或请求被拦截了),那么电脑还是没辙(浏览器会报错)。
    6. 如果域名服务器回应了,那么你的电脑就可以根据域名服务器的应答信息,得到该域名的 IP地址。之后浏览器就会向这个 IP地址 对应的 Web 端口发送 HTTP 请求。
    通常情况下,电脑拿到的(DNS服务器)应答信息是正确的——也就是说,应答中的IP地址确实对应那个域名——这种情况下,你的网络软件就可以正常工作了。

    域名服务器上都会保存一大堆的域名记录(每条记录包含“域名”和“IP地址”)。当收到域名查询的时候,域名服务器会从这堆记录中找到对方想要的,然后回应给对方。如果域名服务器上的某条记录被【人为修改】了(改成错的),那么一旦要查询这条记录,得到的就是错误的结果。这种情况称之为“域名劫持”。“域名劫持”的根源在于:域名服务器上的记录被人给改了。最直接的办法就是不要使用这种流氓 ”通常是电信运营商(ISP)提供的域名服务器,改用国外那些比较靠谱的。目前口碑最好的,大概是 Google提供的两个域名服务器,IP地址分别是 8.8.8.8 和 8.8.4.4 ——这俩不光是地址好记,更重要的是,不会耍流氓。
    域名劫持的危害:比如,把维基百科的流量重定向到XX,篡改自己的域名服务器的记录,把里面跟维基百科相关的域名记录的 IP地址修改为XX的 IP地址。如此一来,假设你用的是这个 ISP 的域名服务器,当你在浏览器输入 http://zh.wikipedia.org/的时候,你的电脑查询到的 IP地址 其实是XX的 IP地址,所以浏览器打开的是“XX”的主页。域名劫持实际上就是把网站重定向了。你想去A,结果成了B。

    域名污染”的原理,简单说来是这样滴:当你的电脑向域名服务器发送了“域名查询”的请求,然后域名服务器把回应发送给你的电脑,这之间是有一个时间差的。如果某个攻击者能够在域名服务器的“DNS应答”还没有到达你的电脑之前,先伪造一个错误的“DNS应答”发给你电脑。那么你的电脑收到的就是错误的信息,并得到一个错误的 IP地址。“域名污染”也叫“域名缓存投毒”。


    (7)列举至少5种前端性能优化的具体方法,简要说明理由。
    A:尽量减少HTTP请求。
    前端优化的黄金准则指导着前端页面的优化策略:只有10%-20%的最终用户响应时间花在接受请求的HTML文档上,剩下的80%-90%时间花在为HTML文档所引用的所有组件(图片、脚本、样式表等)进行的HTTP请求上。因此,改善响应时间的最简单途径就是减少组件的数量,并由此减少HTTP请求的数量。
    ① 图片地图:允许在一张图片上关联多个URL,而目标URL的选择取决于用户单击了图片上的哪个位置。这样多个图片合并成一张图片,这样图片的HTTP请求就减少了。(不过图片地图只支持矩形形状,其他形状不支持。)
    ② CSS Sprites(图像精灵):将多个图片合并到一张单独的图片,这样就大大减少了页面中图片的HTTP请求。(对于当前网络流行的速度而言,不高于200KB的单张图片的所需载入时间基本是差不多的。)
    ③ 内联图片和脚本使用data:URL(Base64编码)模式直接将图片包含在Web页面中而无需进行HTTP请求。但是此种方法存在明显缺陷:- 不受IE的欢迎;- 图片太大不宜采用这种方式,因为Base64编码之后会增加图片大小,这样页面整体的下载量会变大;- 内联图片在页面跳转的时候不会被缓存。(大图片可以使用浏览器的本地缓存,在首次访问的时候保存到浏览器缓存中,典型的是HTML5的manifest缓存机制以及LocalStorage等)。
    ④ 样式表的合并:将页面样式定义、脚本、页面本身代码严格区分开,但是样式表、脚本也不是分割越细越好,因为每多引用一个样式表就增加一次HTPP请求,能合并的样式表尽量合并。一个网站有一个公用样式表定义,每个页面只要有一个样式表就OK啦。

    B:使用内容发布网络(CDN的使用)
    它是一组分布在多个不同地理位置的Web服务器,用于更加有效地向用户发布内容。主要用于发布页面静态资源:图片、css文件、js文件等。如此,能轻易地提高响应速度。

    C:添加Expires头
    浏览器使用缓存来减少HTTP请求的数据,并减小HTTP响应的大小,使页面加载更快。其实就是一句话,把一些css、js、图片在首次访问的时候全部缓存到浏览器本地。(可以使用HTML5提供的本地缓存机制)

    D压缩组件(使用Gzip方式)
    使用各种压缩工具进行对css和js的压缩,甚至可以压缩html。文件压缩变小,自然可以提升。

    E:将CSS样式表放在顶部
    如果将css样式定义放在页面中或者页面底部,会出现短暂白屏或者某一区域短暂白板的情况,这和浏览器的运营机制有关的,不管页面如何加载,页面都是逐步呈现的。所以在每做一个页面的时候,用Link标签把每一个样式表定义放在head中。

    F:将javascript脚本放在底部
    浏览器在加载css文件时,页面逐步呈现会被阻止,直到所有css文件加载完毕,所以要把css文件的引用放到head中去,这样在加载css文件时不会阻止页面的呈现。但是对于js文件,在使用的时候,它下面所有的页面内容的呈现都会被阻塞,将脚本放在页面越靠下的地方,就意味着越多的内容能够逐步呈现。

    G:避免使用CSS表达式
    CSS表达式是动态玩CSS的一种很强大的方式,但是强大的同时也存在很高的危险性。因为css表达式的频繁求值会导致css表达式性能低下。如果真想玩css表达式,可以选用只求值一次的表达式或者使用事件处理来改变css的值。

    H:使用外部javascript和CSS
    内联js和css其实比外部文件有更快的响应速度,那为什么还要用外部呢?因为使用外部的js和css可以让浏览器缓存他们,这样不仅HTML文档大小减少,而且不会增加HTTP请求数量。另外,使用外部js和css可以提高组件的可复用性。

    I:减少DNS查询
    DNS查询有时间开销,通常一个浏览器查找一个给定主机名的IP地址需要20-120ms。缓存DNS:缓存DNS查询可以很好地提高网页性能,一旦缓存了DNS查询,之后对于相同主机名的请求就无需进行再次的DNS查找,至少短时间内不需要。所以在使用页面中URL、图片、js文件、css文件等时,不要使用过多不同的主机名。

    J:精简javascript
    其实W3Cfuns已经给大家准备好精简JS所需的所有工具“前端神器”,这点W3Cfuns为大家做的很不错,在这个规则里我们就用到“JS压缩/混淆/美化工具”最初始的精简方式:就是移除不必要的字符减小js文件大小,改善加载时间。包括所有的注释、不必要的空白字符。

    高级一点的精简方式就是:混淆。它不但会移除不必要的字符,还会改写代码,比如函数和变量的名字会被改成很短的字符串,这样使js代码更简练更难阅读。一旦使用混淆,对于js代码的维护和调试都很复杂,因为有时候混淆之后的js代码完全看不懂。其实实际开发过程中,从文件大小和代码可复用性来说,不仅仅是js代码需要精简,css代码一样也很需要精简。

    K:避免重定向
    重定向的英文是Redirect,用于将用户从一个URL重新跳转到另一个URL。最常见的Redirect就是301和302两种。关于重定向的性能影响这里就不说了,自行查阅相关资料吧。在我们实际开发中避免重定向最简单也最容易被忽视的一个问题就是,设置URL的时候,最后的“/”,有些人有时候会忽略,其实你少了“/”,这时候的URL就被重定向了,所以在给页面链接加URL的时候切记最后的“/”不可丢。

    L:删除重复脚本
    重复的js代码除了有不必要的HTTP请求之外,还会浪费执行js的时间。将你使用的js代码模块化,可以很好地避免这个问题,至于js模块化如何实现,现在有很多可以使用的开源框架。

    M:配置ETag
    Etag(Entity Tag),实体标签,是Web服务器和浏览器用户确认缓存组件的有效性的一种机制。写的很复杂,对我这种非专业的前端开发人员来说,有点过了,关于这个原则有兴趣的自己看吧。

    N:使Ajax可缓存
    针对页面中主动的Ajax请求返回的数据要缓存到本地,当然这个是针对短期内不会变化的数据。如果不确定数据变化周期的话,可以增加一个修改标识的判断,我正常处理过程中会给一些Ajax请求返回的数据增加一个MD5值的判断,每次请求会判断当前MD5是否变化,如果变化了取最新的数据,如果不变化,则不变。

    噼里啪啦说了一堆,14个规则啊,那我们开发过程中要针对这每一个规则对自己的前端代码做check吗?我反正不这么干,做前端页面,尤其是移动网站的页面,我所记住的准则就是:尽量减少页面大小,尽量降低页面响应时间。在页面性能和交互设计之中找平衡点。

    (8)判断字符串是否是这样组成的,第一个必须是字母,后面可以是字母、数字、下划线,总长度为5-20.
    var pattern = /^[a-zA-Z][w]{4,19}$/igm;
    var str = 'a23_dfds_dfdfd';
    alert(pattern.test(str));

    (9)截取字符串abcdefg的efg

        var pattern = /efg/igm;
        var str = 'abcdefgefgefg';
                
        if (pattern.test(str)) {        //检测是否有efg                               
        	alert(str.substr(str.indexOf('efg'), 3));        //取出长度为3
        }
    

    (10)   将构造函数当作函数

        function Box(name, age) {
            this.age = age;
            this.name = name;
            this.run = function () {
                return this.name + this.age + "runing....";
            };
        };
       //创建一个对象,正常调用。
        var box = new Box('hg', 123);
        alert(box.run());
        //全局运行这个函数,属性和方法添加给window,this是指向global的指针
        Box('wj', 223);
        alert(this.run());
        alert(window.run());
       //在o对象中调用Box,所以o就具有了Box的属性
        var o = {};
        Box.call(o, 'lz', 123);
        alert(o.run());
    

    (11)判断一个字符窜中出现最多的字符

            var str = 'dffjkjdsfkldsfknnjfknkjfdsfdsfn';
            var obj = {};
            function hasMostStr(str)
            {
                var pattern = /^[w]+/igm;
                if (!pattern.test(str))
                    return ;
                
                for (var i = 0; i != str.length; i++)
                {
                    var charector = str.charAt(i);
                    if (typeof  charector!= 'string')
                        break;
                    
                    if (!(charector in obj))
                    {
                        obj[charector] = 1;
                    }
                    else {
                        obj[charector]++;
                    }
                }
            }
    
            function writeObj(obj)
            {
                if (typeof obj != 'object') 
                {
                    return;
                }
                var documents = "";
                for (var pro in obj)
                {
                    documents += pro + " = " + obj[pro] + "<br />";
                }
                
                document.write(documents);
            }    
    
    
            hasMostStr(str);
            writeObj(obj);
    

    (12)规避javascript多人开发函数重名问题
    (1) 可以开发前规定命名规范,根据不同开发人员开发的功能在函数前加前缀。
    (2) 将每个开发人员的函数封装到类中,调用的时候就调用类的函数,即使函数重名只要类名不重复就可以。

    (13)JavaScript继承有哪两种形式形式,进行描述
    对象冒充:在子类构造方法内,通过apply/call将this作为参数传入。
    优点:
      可以向父类构造方法传递参数,即给apply第二个参数:arguments;
      父类中的属性都被复制到子类实例中,属性之间无干扰,无论是引用类型还是封装类型。
    缺点:
      每一个实例对象都拥有一份父类方法的拷贝,互不干扰,所以无法统一修改;
      无法拥有父类原型中定义的方法;
      子类的实例对象不能通过 instanceof 操作符判断是否是父类的实例。
    原型链:指定子类的prototype为父类的一个实例对象。
    优缺点和构造函数借用刚好相反。
    这里特别说明下属性之间相互干扰(对应构造函数借用的优点2)。


    组合式继承:
    上面两种方式互补一下,即用构造方法借用来继承父类属性,用原型链来继承父类方法。
    优点:
      封装保护了内部数据的完整性;
      封装使对象的重构更轻松;
      弱化模块间的耦合,提高对象的可重用性;
      有助于避免命名空间冲突。
    缺点:
      私用方法很难测试;
      必须与复杂的作用域链打交道,使错误调度更困难;
      容易形成过度封装;
      JavaScript并不原生支持封装,所以在JavaScript中实现封装存在复杂性的问题。

    (14)编写一个方法,求一个字符串的字节长度。

    function GetBytes(str) {
              var len = str.length;
              var bytes = len;
              for (var i = 0; i < len; i++)
              {
                      if (str.charCodeAt(i) > 255) //中文都大于255
                      bytes++;
              }
              return bytes;
    }
    
    alert(GetBytes("你好,as"));        //7
    
    charCodeAt和charAt类似,前者返回uncode编码,后者返回字符。
    

    (15)编写一个方法 去掉一个数组的重复元素

            var arr = [1,2,3,4,5,1,3,2,3,4,2,2];
            function haveUnqueArray(arr) {
                var o = [];    
                for (var pro in arr) {
                    var temp = arr[pro];
                    if (!o[temp]) {          //判断元素是否在数组中。
                        o.push(temp);         //不再就添加
                    }
                }
                return o;
            }
    
            alert(haveUnqueArray(arr));
    


    (16)写出this的典型应用

    1---在html元素事件属性中使用,如
    <input type=”button” onclick="showInfo(this);" value="点击一下"/>
    
    2---构造函数
    function Animal(name, color) {
       this.name = name;
       this.color = color;
    }
    3---内联的script中
    <input type="button" id="text" value="点击一下" />
    <script type="text/javascript">
      var btn = document.getElementById("text");
      btn.onclick = function() {
      alert(this.value);         //此处的this是按钮元素--弹出点击一下
    }
    </script>
    4---CSS expression表达式中使用this关键字 <table width="100px" height="100px"> <tr> <td>   <div style="expression(this.parentNode.width);">div element</div> </td> </tr> </table>

     

    (17)JavaScript中如何检测一个变量是一个String类型?请写出函数实现。
    String类型有两种生成方式:
    (1)Var str = “hello world”;            //string类型
    (2)Var str2 = new String(“hello world”);    //对象生成的

    function IsString(str){
        return (typeof str == "string" || str.constructor == String);
    }
    var str = "";
    alert(IsString(1));
    alert(IsString(str));
    alert(IsString(new String(str)))
    

    (18)JavaScript事件委托的技术原理
    事件委托,就是事件,比如onclick,onmouseover,onmouseout.委托的意思就是让别人来做,

    原理就是利用冒泡的原理,把事件加载到父级标签上,触发执行效果。

    好处1:提高性能。不需要for循环为每一个元素都加入事件。

    好处2,新添加的元素还会有之前的事件。很可能此时js已经加载完成了,新加入的节点无法在做出反应事件了,就还需要重新加载一次js。

    其实要是对属性做操作,事件委托,就可以代替闭包和添加新的属性,来解决对元素的循环操作。并且提升了性能。

    <ul id="parent-list">
                <li id="post-1">Item 1</li>
                <li id="post-2">Item 2</li>
                <li id="post-3">Item 3</li>
                <li id="post-4">Item 4</li>
                <li id="post-5">Item 5</li>
                <li id="post-6">Item 6</li>
            </ul>
    <script>
        // 找到父元素,添加监听器...
      //这里只写了W3C的,IE是attachEvent document.getElementById("parent-list").addEventListener("click", function(ev) { // e.target是被点击的元素! // 如果被点击的是li元素 // var ev = ev || window.event; // var target = ev.target || ev.srcElement; if(ev.target && ev.target.nodeName == "LI") { // 找到目标,输出ID! // console.log("List item ",ev.target.id.substr(ev.target.id.length - 1)," was clicked!"); alert("List item " + ev.target.id.substr(ev.target.id.length - 1)); } }, false); </script>

     

    (19)JS添加事件
    第一种: obj.onclick = method1;
    obj.onclick = method2;
    obj.onclick = method3; 最后只有medthod3保存了
    第二种:用addEventListener(‘click’, function, false);
    False 是由里向外,true是由外向内。
    IE还有一个attachEvent(‘click’, function);

    第三种写法 : obj['onclick']或者obj['click'] = function () {};

    IE要加on W3C,就不加。 

    (20)冒泡事件是什么?如何阻止事件冒泡和默认事件。
    事件冒泡: 当一个元素上的事件被触发的时候,比如说鼠标点击了一个按钮,同样的事件将会在那个元素的所有祖先元素中被触发。这一过程被称为事件冒泡;

    这个事件从原始元素开始一直冒泡到DOM树的最上层。

    阻止冒泡事件: cancelBubble(IE)和stopPropagation(FF)

        function doSomething (obj, evt) { 
            alert(obj.id); 
            var e = (evt) ? evt : window.event; 
            //判断浏览器的类型,在基于ie内核的浏览器中的使用cancelBubble
            if (window.event) 
            { 
                e.cancelBubble=true; 
            } 
            else 
            { 
                //e.preventDefault(); //在基于firefox内核的浏览器中支持做法stopPropagation
                e.stopPropagation(); 
            } 
        } 
    

    防止冒泡

    w3c的方法是e.stopPropagation(),IE则是使用e.cancelBubble = true

    阻止默认行为

    w3c的方法是e.preventDefault(),IE则是使用e.returnValue = false;


    (21)解释jsonp的原理,以及为什么不是真正的ajax
    动态创建script标签,回调函数,Ajax是页面无刷新请求数据操作。
    JSONP(JSON with Padding)是JSON的一种“使用模式”,

    可用于解决主流浏览器的跨域数据访问的问题

    由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的<script> 元素是一个例外。

    利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。

    用 JSONP 抓到的资料并不是 JSON,而是任意的JavaScript,用 JavaScript 直译器执行而不是用 JSON 解析器解析。

     


    (22)javascript的本地对象,内置对象和宿主对象
    本地对象:
    Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError
    由此可以看出,简单来说,本地对象就是 ECMA-262 定义的类(引用类型)
    内置对象:
    ECMA-262 只定义了两个内置对象,即 Global 和 Math (它们也是本地对象,根据定义,每个内置对象都是本地对象)。

    本地对象,就是那些官方定义好了的对象。内置对象是本地对象的一种,其只包含Global对象和Math对象。而宿主对象则是那些官方未定义,你自己构建的对象加上DOM和BOM对象组成的。

    (23)document load 和document ready的区别
      Document.onload 是在结构和样式加载完才执行js
      Document.ready原生种没有这个方法,jquery中有$().ready(function)DOM结构绘制完毕后就执行,不必等到加载完毕。


    执行时间
      window.onload      必须等到页面内包括图片的所有元素加载完毕后才能执行。
      $(document).ready()    是DOM结构绘制完毕后就执行,不必等到加载完毕。

    编写个数不同
      window.onload      不能同时编写多个,如果有多个window.onload方法,只会执行一个
      $(document).ready()    可以同时编写多个,并且都可以得到执行

    简化写法
      window.onload              没有简化写法
      $(document).ready(function(){})      可以简写成$(function(){});

    (24)简述JavaScript封装。
    封装可以被定义为对对象的内部数据表现形式和实现细节进行隐藏。通过封装可以强制实施信息隐藏。
    在JavaScript中,并没有显示的声明私有成员的关键字等。

    所以要想实现封装/信息隐藏就需要从另外的思路出发。我们可以使用闭包的概念来创建只允许从对象内部访问的方法和属性,来达到封装的要求。

    基本方式
    一般来说,我们学用的有三种方法来达到封装的目的。
    使用this.XXX来声明一个变量,然后再声明getXXX、setXXX等取值、赋值的方法。
    使用this._XXX来声明一个变量,然后再声明getXXX、setXXX等取值、赋值的方法。

    利用“函数作用域”这一个概念来做。
    1. 门户大开型            
           var Book = function(val){
                    this.setValue(val);
                };
                Book.prototype = {
                    setValue: function(val){
                        this.val = val;
                    },
                    getValue: function(){
                        return this.val;
                    },
                };
                var book = new Book(1);
                alert(book.val);
    
    使用这种方法实现的封装,虽然实现了取值器与赋值器以保护私有属性。但是在实际使用中,私有属性依然可以从外部访问,所以从根本上讲,没有实现封装。

    2. 用命名规范进行区别 var Book = function(val){ this.setValue(val); }; Book.prototype = { setValue: function(val){ this._val = val; }, getValue: function(){ return this._val; }, }; var book = new Book(1); alert(book._val); 使用这种方法与第一种类似,区别在于使用不同的命名来保护私有属性的使用。但是,从实际应用来说其仍然没有实现封装。 3. 使用函数作用域        var Book = function() { var isbn; //这里是局部变量。函数作用域。 this.setIsbn = function(newIsbn){ isbn = newIsbn; }; this.getIsbn = function(){ return isbn; }; } var book = new Book(); book.setIsbn(1); alert(book.getIsbn()); 由于在JavaScript的函数中声明的变量是有作用域的,所以使用这种方法可以避免在外部直接访问私有属性。基本达到封装所要求的内容。 这里要注意的是,我们在函数的内部,可以使用this.XXX以及var来声明变量。区别是使用this.XXX声明的变量在外部是可以访问的。
    使用var声明的变量,由于受到函数作用域的保护,在函数的外部是无法直接访问的。

      

    (25)Js中this具体的用法总结如下

    1. 全局变量和全局函数附属于全局对象(window),因此使用”var”或”this”两种方法定义全局变量是等效的。

      


    2. 执行上下文和作用域不同。执行上下文在运行时确定,随时可能改变,而作用域则在定义时确定,永远不会变。这个跟MFC的一个性质很像,运行时动态识别。

    	//获取对象构造函数名称
    	function type(obj) {
    		return obj && obj.constructor && obj.constructor.toString().match(/functions*([^(]*)/)[1];
    	}
    
    	function test() {
    		alert(type(this));
    	}
    
    	function A() {
    		this.fun = test;
    	}
    
    	function B() {
    		this.fun = test;
    	}
    
    
    	var a = new A();  
    	var b = new B();
    	test();     // window
    	a.fun();     // A
    	b.fun();    // B
    

    3. 如果当前执行的是一个对象的方法,则执行上下文就是这个方法所附属的对象。

    	function test () {
    		alert(this.name);
    	}
    
    	function AAA() {
    		this.name = 'hg';
    		this.test1 = test;
    
    		function BBB() {
    			this.name = 'gh';
    			this.test2 = test;
    		}
    		this.bbb = new BBB();
    
    	}
    
    	var aaa = new AAA();
    	aaa.test1();     //hg
    	aaa.bbb.test2();  //gh

    说明,函数test中的this指向临近的这个对象。这个对象方法,执行的就是上下文所对应的对象。


    4. 如果当前是一个创建对象的过程或者执行一个对象的方法,则执行上下文就是这个正在被创建的对象。

    5. 如果一个方法在执行时没有明确指定附属对象,则这个方法的上下文为全局对象。

    6. 使用call和apply可以改变对象的执行上下文。

     

    (26)简述下cookie的操作,还有cookie的属性都知道哪些。
    cookie是浏览器提供的一种机制,它将document 对象的cookie属性提供给JavaScript。

    可以由JavaScript对其进行控制,而并不是JavaScript本身的性质。cookie是存于用户硬盘的一个文件,这个文件通常对应于一个域名,当浏览器再次访问这个域名时,便使这个cookie可用。

    因此,cookie可以跨越一个域名下的多个网页,但不能跨越多个域名使用。可用在保存用户登录状态。跟踪用户行为。定制页面。创建购物车。

    $.cookie(‘cookieName’,'cookieValue’,{expires:7,path:’/',domain: ‘chuhoo.com’,secure: false,raw:false});
    注:expires:有效时间;path:设置能够读取cookie的顶级目录;domain: 创建cookie所在网页所拥有的域名;secure:默认是false,如果为true,cookie的传输协议需为https;raw:默认为 false,读取和写入时候自动进行编码和解码(使用encodeURIComponent编码,使用decodeURIComponent解码),关闭 这个功能,请设置为true。

    (27)前端优化知识都知道哪些?
    答:a 减少http请求,合并css、js文件,apache的ant。
    b 减少请求文件的大小,压缩css、js文件,在线javascript compress。
    c 采用sprite拼接图片。
    d 如果有广告栏之类的模块,用iframe。
    e 将js文件放到末尾,这个页面显示就不必等js文件加载完以后再显示,也就是页面不会出现空白状态。

    (28)瀑布流布局或者流式布局是否有了解。
    答:瀑布流布局:采用绝对定位来给每张图片或者模块定位。
    流式布局:采用浮动式给模块定位。可以做出响应式布局。

     

    (29)JavaScript中如何对一个对象进行深度clone

    克隆方法实在很多,这里只是举例一个。

    function cloneObject(o) {
        if(!o || 'object' !== typeof o) {
            return o;
        }
        var c = 'function' === typeof o.pop ? [] : {};
        var p, v;
        for(p in o) {
            if(o.hasOwnProperty(p)) {
                v = o[p];
                if(v && 'object' === typeof v) {
                    c[p] = Ext.ux.clone(v);
                }
                else {
                    c[p] = v;
                }
            }
        }
        return c;
    };
    

    (30)请实现,鼠标点击页面中的任意标签,alert该标签的名称.(注意兼容性)

    <script type="text/javascript">
    	document.onclick = function(evt){
    		var e = window.event || evt;
    		var tag = e["target"] || e["srcElement"];
    		alert(tag.tagName);
    	};
    </script>
    

     

     


    (31)作用域的问题

    (1)var a = 6; 
        setTimeout(function () {
            alert(a);
            a = 666;
        }, 1000);
        a = 66;
     Alert是打印66的,因为1s之后,a==66。三个a都是全局变量。
    (2)
       var a = 6; SetTimeout(function () { alert(a); var a = 666; }, 1000); a = 66;
    打印的是undefined,因为在function内部又定义了var的局部变量。 还有一点要记住:setTimeout(function,time);function是一个全局的函数。就是this。Function()这个this是全局不是某一个对象
    var a = 0;        //定义全局变量 function A(){ this.a = 1;      //对象变量a setTimeout(function(){ //函数和变量执行的是全局作用域 this.a = 2;    //this 指向的是全局作用域 a=2 try{ this.b="b"; throw '';    //这里抛出了一个异常 } catch(e){ this.b='bb'; //全局的b设置为bb } },0); this.b = "bbb"; //定义对象内的b变量 } var aa = new A();      //定义了对象,运行了setTimeout setTimeout(function(){ console.log(aa.a);     //1 console.log(window.a);  //2 console.log(aa.b);     //bbb console.log(window.b)   //bb },0);

     (32) 判断输出

    var a = 10;  
    function  bb ()
    {	
    	alert(a);  
    	var a=2; 
    	alert(a);
    }   
    bb();
    

    undefined

    2

  • 相关阅读:
    最快速的Android开发环境搭建ADT-Bundle及Hello World
    android sdk manager 无法更新解决方法
    ADO.NET 新特性之SqlBulkCopy
    WCF错误:413 Request Entity Too Large
    构建高性能的ASP.NET应用程序
    编写高性能Web应用程序的10个技巧
    很不错的jQuery学习资料和实例
    学习jQuery之旅
    50个常用的JQuery代码
    机器学习瓶颈
  • 原文地址:https://www.cnblogs.com/hgonlywj/p/4842596.html
Copyright © 2011-2022 走看看