`

面试总结

阅读更多

 

    1. 跨域问题

      只要协议、域名、端口有任何一个不同,都被当作是不同的域。
      • a.baidu.com访问b.baidu.com 是跨域;
      • a.baidu.com:8080访问a.baidu.com:80 是跨域;
      • http://a.baidu.com访问https://a.baidu.com 是跨域

      JSONP的优缺点

      JSONP的优点是:它不像 XMLHttpRequest 对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。
      JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行 JavaScript 调用的问题。

      通过修改document.domain来跨子域

      在两个不同子域名的页面中都加上相同的document.domain = 主域名,即可实现。
      修改 document.domain 的方法只适用于不同子域的框架间的交互。

      使用window.name来进行跨域

      在父页面定义window.name = '要传递的数据';iframe页面通过window.parent.name来获取;如果嵌套多层可以用widnow.top.name 来获取顶层window的名称

      使用HTML5的window.postMessage方法跨域

      postMessage(data,origin)方法接受两个参数
      1.data:要传递的数据,html5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器都做到了这点儿,部分浏览器只能处理字符串参数,所以我们在传递参数的时候需要使用JSON.stringify()方法对对象参数序列化,在低版本IE中引用json2.js可以实现类似效果。
      2.origin:字符串参数,指明目标窗口的源,协议+主机+端口号[+URL],URL会被忽略,所以可以不写,这个参数是为了安全考虑,postMessage()方法只会将message传递给指定窗口,当然如果愿意也可以建参数设置为"*",这样可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。
    2. 数据分离

      MVC

      视图(View):用户界面。
      控制器(Controller):业务逻辑
      模型(Model):数据保存

      View 传送指令到 Controller
      Controller 完成业务逻辑后,要求 Model 改变状态
      Model 将新的数据发送到 View,用户得到反馈
      所有通信都是单向的。

      MVP

      MVP 模式将 Controller 改名为 Presenter,同时改变了通信方向。

      1. 各部分之间的通信,都是双向的。
      2. View 与 Model 不发生联系,都通过 Presenter 传递。Presenter是主持人的意思
      3. View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。

      MVVM

      MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。

      唯一的区别是,它采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然。Angular 和 Ember 都采用这种模式。
    3. 代码优化

      1. 尽量减少HTTP请求数
      2. 减少DNS查找
      3. 避免重定向
      4. 让Ajax可缓存
      5. 延迟加载组件
      6. 预加载组件
      7. 减少DOM元素的数量
      8. 跨域分离组件
      9. 尽量少用iframe
      10. 杜绝404
      11. 避免使用CSS表达式
      12. 选择舍弃@import
      13. 避免使用滤镜
      14. 把样式表放在顶部
      15. 去除重复脚本
      16. 尽量减少DOM访问
      17. 用智能的事件处理器
      18. 把脚本放在底部
      19. 把JavaScript和CSS放到外面
      20. 压缩JavaScript和CSS
      21. 优化图片
      22. 优化CSS Sprite
      23. 不要用HTML缩放图片
      24. 用小的可缓存的favicon.ico(P.S. 收藏夹图标)
      25. 给Cookie减肥
      26. 把组件放在不含cookie的域下
      27. 保证所有组件都小于25K
      28. 把组件打包到一个复合文档里
      29. Gzip组件
      30. 避免图片src属性为空
      31. 配置ETags
      32. 对Ajax用GET请求
      33. 尽早清空缓冲区
      34. 使用CDN(内容分发网络)
      35. 添上Expires或者Cache-Control HTTP头
    4. js如何封装函数

      	function Person() {
      	   this.name = "jee";
      	   this.age = 25;
      	   this.getName = function() {
      	      return this.name;
      	   }
      	}
      	 
      	var person = new Person();
      	alert(person.age);
      	alert(person.getName());
      
    5. 异步加载方式

      1. defer,只支持IE

        defer 属性规定是否对脚本执行进行延迟,直到页面加载为止。

        	<script type="text/javascript" defer="defer">
        	alert(document.getElementById("p1").firstChild.nodeValue); 
        	</script>
        
      2. async: async的定义和用法(是HTML5的属性) ,async 属性规定一旦脚本可用,则会异步执行。
        	<script type="text/javascript" src="demo_async.js" async="async"></script>
        
        注释:async 属性仅适用于外部脚本(只有在使用 src 属性时)。
        注释:有多种执行外部脚本的方法:
        •如果 async="async":脚本相对于页面的其余部分异步地执行(当页面继续进行解析时,脚本将被执行)
        •如果不使用 async 且 defer="defer":脚本将在页面完成解析时执行
        •如果既不使用 async 也不使用 defer:在浏览器继续解析页面之前,立即读取并执行脚本
      3. 创建script,插入到DOM中,加载完毕后callBack
        	function loadScript(url, callback){ 
        		var script = document.createElement_x("script") 
        		script.type = "text/javascript"; 
        		if (script.readyState){ //IE 
        			script.onreadystatechange = function(){ 
        				if (script.readyState == "loaded" || script.readyState == "complete"){ 
        					script.onreadystatechange = null; 
        					callback(); 
        				} 
        			}; 
        		}else{ //Others: Firefox, Safari, Chrome, and Opera 
        			script.onload = function(){ 
        				callback(); 
        			}; 
        		} 
        		script.src = url; 
        		document.body.appendChild(script); 
        	} 
        
    6. 写一个递归1+2+3+4+5...+30

      	function ccc(n){
      		var sum = 0;
      		for(var i=1; i<=n ;i++){
      			sum += i;
      		}
      		return sum;
      	};
      	console.log(ccc(30));
      	function ddd(n){
      		if(n<=1){
      			return 1;
      		};
      		return n+ddd(n-1);
      	};
      	console.log(ddd(30));
      

      写一个递归1-2+3-4+5...-100

      	/*function ccc(n){
      		if(n<=1){
      			return 1;
      		}else if(n==2){
      			return -1;
      		}else if(n==3){
      			return 2;
      		};
      
      		return ccc(n-3) - ccc(n-2) + ccc(n-1) - n;
      	};不太对,n=4的时候得0,还是得拆成两种情况为好*/
      
      	function ccc(n){
      		if(n==1){//逐渐向1趋近,直至循环终止
      			return 1;
      		}else{
      			var num = n%2==0 ? -n : n;//n不能变需要递减
      			return num + ccc(n-1);
      		}
      	}
      	console.log(ccc(100));//-50
      
    7. XSS如何攻防

      1. 输入过滤
        对用户的所有输入数据进行检测,比如过滤其中的“<”、“>”、“/”等可能导致脚本注入的特殊字符,或者过滤“script”、“javascript”等脚本关键字,或者对输入数据的长度进行限制等等。同时,我们也要考虑用户可能绕开    ASCII码,使用十六进制编码来输入脚本。因此,对用户输入的十六进制编码,我们也要进行相应的过滤。只要能够严格检测每一处交互点,保证对所有用户可能的输入都进行检测和XSS过滤,就能够有效地阻止XSS攻击。
      2. 输出编码
        通过前面对XSS攻击的分析,我们可以看到,之所以会产生XSS攻击,就是因为Web应用程序将用户的输入直接嵌入到某个页面当中,作为该页面的HTML代码的一部分。因此,当Web应用程序将用户的输入数据输出到目标    页面中时,只要用HtmlEncoder等工具先对这些数据进行编码,然后再输出到目标页面中。这样,如果用户输入一些HTML的脚本,也会被当成普通的文字,而不会成为目标页面HTML代码的一部分得到执行。
      3. Cookie防盗
        利用XSS攻击,攻击者可以很方便地窃取到合法用户的Cookie信息。因此,对于Cookie,我们可以采取以下的措施。首先,我们要尽可能地避免在Cookie中泄露隐私,如用户名、密码等;其次,我们可以将Cookie信息利用MD5等Hash算法进行多次散列后存放;再次,为了防止重放攻击,我们也可以将Cookie和IP进行绑定,这样也可以阻止攻击者冒充正常用户的身份。

      CSRF 攻击如何攻防

      CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。 你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全。

      CSRF 防御技巧

      1. 验证码
        几乎所有人都知道验证码,但验证码不单单用来防止注册机的暴力破解,还可以有效防止CSRF的攻击。验证码算是对抗CSRF攻击最简洁有效的方法。但使用验证码的问题在于,不可能在用户的所有操作上都需要输入验证码.只有一些关键的操作,才能要求输入验证码。不过随着HTML5的发展。利用canvas标签,前端也能识别验证码的字符,让CSRF生效。
      2. Token
        CSRF能攻击成功,根本原因是:操作所带的参数均被攻击者猜测到。既然知道根本原因,我们就对症下药,利用Token。当向服务器传参数时,带上Token。这个Token是一个随机值,并且由服务器和用户同时持有。当用户提交表单时带上Token值,服务器就能验证表单和session中的Token是否一致。
    8. Get和Post方法的区别

      Http协议定义了很多与服务器交互的方法,最基本的有4种,分别是GET,POST,PUT,DELETE. 一个URL地址用于描述一个网络上的资源,而HTTP中的GET, POST, PUT, DELETE就对应着对这个资源的查,改,增,删4个操作。 我们最常见的就是GET和POST了。GET一般用于获取/查询资源信息,而POST一般用于更新资源信息.

      我们看看GET和POST的区别

      1. GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,如EditPosts.aspx?name=test1&id=123456. POST方法是把提交的数据放在HTTP包的Body中.
      2. GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.
      3. GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值。
      4. GET方式提交数据,会带来安全问题,比如一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码.
    9. 面向对象的属性有哪些?

      1. 继承
      2. 多态
      3. 封装
    10. http状态码

      200 - 服务器成功返回网页 404 - 请求的网页不存在 503 - 服务不可用
    11. img是行内元素?能设置宽度高度吗?这一类的元素叫什么,还有哪些?

      从元素本身的特点来讲,可以分为不可替换元素和替换元素。

      1. 不可替换元素:(X)HTML 的大多数元素是不可替换元素,即其内容直接表现给用户端(例如浏览器)。
      2. 替换元素:替换元素就是浏览器根据元素的标签和属性,来决定元素的具体显示内容。

        例如浏览器会根据img标签的src属性的值来读取图片信息并显示出来,而如果查看(X)HTML代码,则看不到图片的实际内容;又例如根据input标签的type属性来决定是显示输入框,还是单选按钮等。
        替换元素一般有内在尺寸,所以具有width和height,可以设定。例如你不指定img的width和height时,就按其内在尺寸显示,也就是图片被保存的时候的宽度和高度。 对于表单元素,浏览器也有默认的样式,包括宽度和高度

    12. CSS3中各个浏览器内核兼容的设置

      	CSS3中-moz、-ms、-webkit和-o分别代表什么意思  
      	  
      	  
      	1、-moz-:代表FireFox浏览器私有属性  
      	  
      	  
      	2、-ms-:代表IE浏览器私有属性  
      	  
      	  
      	3、-webkit-:代表safari、chrome浏览器私有属性  
      	  
      	  
      	4、-o-:代表opera浏览器私有属性  
      
    13. 闭包的理解

      答闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
    14. js的数据类型

      基本类型:String、Number、Boolean、Null、Undefined
      引用类型:Object
    15. 函数节流

      以下场景往往由于事件频繁被触发,因而频繁执行DOM操作、资源加载等重行为,导致UI停顿甚至浏览器崩溃。
      1. window对象的resize、scroll事件
      2. 拖拽时的mousemove事件
      3. 射击游戏中的mousedown、keydown事件
      4. 文字输入、自动完成的keyup事件
      实际上对于window的resize事件,实际需求大多为停止改变大小n毫秒后执行后续处理;而其他事件大多的需求是以一定的频率执行后续处理。针对这两种需求就出现了debounce和throttle两种解决办法。
      	//法一:
      	 var throttle = function(fn, delay){
      	  	var timer = null;
      	  	return function(){
      	  		var context = this, args = arguments;
      	  		clearTimeout(timer);
      	  		timer = setTimeout(function(){
      	  			fn.apply(context, args);
      	  		}, delay);
      	  	};
      	};
      	window.onresize = throttle(myFunc, 100);
      	
      	//法二:
      	var throttle = function(delay, action){
      	  var last = 0return function(){
      	    var curr = +new Date()
      	    if (curr - last > delay){
      	      action.apply(this, arguments)
      	      last = curr 
      	    }
      	  }
      	}
      
    16. call apply 的区别,this 的指向

      对于apply和call两者在作用上是相同的,但两者在参数上有区别的:

      1. 第一个参数都是要传入给当前对象的对象,及函数内部的this
      2. 后面的参数都是传递给当前对象的参数

      对于第一个参数意义都一样,但对第二个参数:

      1. apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入
      2. 而call则作为call的参数传入(从第二个参数开始)
      如 func.call(func1,var1,var2,var3)对应的apply写法为:func.apply(func1,[var1,var2,var3])

      使用apply的好处是可以直接将当前函数的arguments对象作为apply的第二个参数传入
      	   var func=new function(){this.a="func"}
      	    var myfunc=function(x){
      	        var a="myfunc";
      	        alert(this.a);
      	        alert(x);
      	    }
      	    myfunc.call(func,"var");
      	    //分别弹出了func和var。到这里就对call的每个参数的意义有所了解了
      
    17. html5标签兼容低版本浏览器

      1. 方法一:加一句js,表示我要创建一个新标签,IE你别再说你不认识了!
        	document.createElement("这里写标签名");
        
      2. 插件:Bsie(鄙视IE),这个名字很有趣,其实看完它的源码后会发现,它就是帮我们把所有的h5标签都创建了一遍,免去了我们手工创建的时间。
      3. 插件:html5shiv:和上面的插件功能一样,感觉身边的朋友用这个的比较多,自己做项目的时候也是用的这个,看完它的源码会发现一个小细节,它会帮我们把不是h5标签里的自定义标签也创建一次,这意味着我们在创建一个自定义标签的时候,不用考虑这个标签会不会生效了,真是贴体入微。
    18. 冒泡排序

      	function bubbleSort(arr){
      		for(var i=0; i<arr.length; i++){
      			for(var j=0; j<arr.length-i; j++){
      				toCon(j,j+1);
      			}
      		}
      
      		function toCon(pre, nex){
      			var tmp = '';
      			if(arr[pre] > arr[nex]){
      				tmp = arr[pre];
      				arr[pre] = arr[nex];
      				arr[nex] = tmp;
      			}
      		}
      
      		return arr;
      	}
      	var arr = [4,2,1,5,7]
      	console.log(bubbleSort(arr));
      

      选择排序

      	function chooseSort(arr){
      
      		if(arr.length == 1){
      			return arr;
      		}
      
      		var iMin = arr[0];
      		var iIndex = 0;
      
      		for(var i=0; i<arr.length; i++){
      			if(arr[i] < iMin){
      				iMin = arr[i];
      				iIndex = i;
      			}
      		}
      
      		var pre = arr.splice(iIndex, 1);
      		return pre.concat( xuanze(arr) );
      	}
      	var arr = [4,2,1,5,7]
      	console.log(chooseSort(arr));
      
    19. 阻止冒泡的方法

      	//阻止事件冒泡
      	function stopPropagation(event){
      		if(event.stopPropagation){
      			event.stopPropagation();
      		}else{
      			event.cancelBubble = true;
      		};
      	};
      
    20. 截取url指定内容

      	function getSearchString(key) {
      	    // 获取URL中?之后的字符
      	    var str = location.search;
      	    str = str.substring(1,str.length);
      	    
      	    // 以&分隔字符串,获得类似name=xiaoli这样的元素数组
      	    var arr = str.split("&");
      	    var obj = new Object();
      	    
      	    // 将每一个数组元素以=分隔并赋给obj对象    
      	    for(var i = 0; i < arr.length; i++) {
      	        var tmp_arr = arr[i].split("=");
      	        obj[decodeURIComponent(tmp_arr[0])] = decodeURIComponent(tmp_arr[1]);
      	    }
      	    return obj[key];
      

      例如:URL为http://localhost/training/test_javascript.html?name=xiaoli&sex=man,调用getSearchString("name")会得到xiaoli。

    21. HTML语义化的好处;

      1. 为了在没有CSS的情况下,页面也能呈现出很好地内容结构、代码结构:为了裸奔时好看;
      2. 用户体验:例如title、alt用于解释名词或解释图片信息、label标签的活用;
      3. 有利于SEO:和搜索引擎建立良好沟通,有助于爬虫抓取更多的有效信息:爬虫依赖于标签来确定上下文和各个关键字的权重;
      4. 方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以意义的方式来渲染网页;
      5. 便于团队开发和维护,语义化更具可读性,是下一步吧网页的重要动向,遵循W3C标准的团队都遵循这个标准,可以减少差异化。
    22. 行内元素inline-block,块级元素block的区别;

      内联元素是不可以控制宽和高、margin等;并且在同一行显示,不换行。 块级元素时可以控制宽和高、margin等,并且会换行。

      1. inline:使用此属性后,元素会被显示为内联元素,元素则不会换行。
      2. block:使用此属性后,元素会被现实为块级元素,元素会进行换行。
      3. inline-block:是使元素以块级元素的形式呈现在行内。意思就是说,让这个元素显示在同一行不换行,但是又可以控制高度和宽度,这相当于内敛元素的增强。
    23. 为了设宽度,将多个行内元素span设为了inline-block,但是会造成元素之间有空白,为什么,怎么解决?

      当原素被转换为inline-block显示的时候,那么该元素会具有inline的一些属性,所以当你在标签之间换行的时候会产生空格,inline-block之间的间距就是一个空格的位置.
      解决办法:设置父元素font-size:0;子元素重新设置自己的font-size;
    24. CSS的盒模型有几种,IE一定是IE模式的吗,而是正常模式和非正常模式,区别是什么?

      两种:content-box和border-box

      主要区别是二者的盒子的宽度是否包含元素的边框和内边距。

      border-box包含元素的边框和内边距

      使用方法:box-sizing:content-box; box-sizing:border-box

    25. CSS 选择器的优先级标准

      行内样式 > id选择器优先级 > 类class选择器优先级 > 标签选择器优先级

    26. 不定宽高的水平垂直居中

      1. 最简单的flex布局,外层容器加上如下样式即可
        display: flex;
        justify-content: center;
        align-items: center;
        
      2. 利用table-cell

        外层容器

        display:table-cell;
        text-align:center;
        vertical-align:middle;	
        

        内部元素

        vertical-align:middle;
        display:inline-block;	
        
      3. 使用CSS3 transform

        外层容器

        display:relative	
        

        内部元素

        transform: translate(-50%,-50%);
        position: absolute;
        top: 50%;
        left: 50%;	
        
    27. 字符串常用的函数,数组常用的函数,具体的使用方法

      见博客: 数组常用方法 字符串常用方法
    28. js中几种判断数据类型的方法:typeof、instanceof与constructor

      alert("typeof(1):" + typeof(1));//number
      alert("typeof(\"abc\"):" + typeof("abc"));//string
      alert("typeof(true):" +typeof(true));//boolean
      alert("typeof(2009-2-4):" + typeof(2009-2-4));//number
      alert("typeof(\"2009-2-4\"):" + typeof("2009-2-4"));//string
      alert("typeof(m):" + typeof(m));//undefined
      var d=new Date();
      alert("typeof(d):" + typeof(d));//object
      function Person(){};
      alert("typeof(Person):" + typeof(Person));//function
      var a=new Array();
      alert("typeof(a):" + typeof(a));//object
      alert("a instanceof Array:" + (a instanceof Array));
      var h=new Person();
      var o={};
      alert("h instanceof Person:" + (h instanceof Person));//true
      alert("h instanceof Object:" + (h instanceof Object));//true
      alert("o instanceof Object:" + (o instanceof Object));//true
      alert(typeof(h));//object
      
      	var j=2;
      	alert(typeof(j));//number
      	alert("j.constructor:" + j.constructor);//function …
      	alert(typeof(j.constructor));//function
      	VM1002:2 alert: number
      	VM1002:3 alert: j.constructor:function Number() { [native code] }
      	VM1002:4 alert: function
    29. 常见题目:

// 1. delete 只能删除对象下面的属性,不能删除变量和参数
// 2. 外层的变量,内层可以找到(全局),内层的变量,外层找不到(局部)
// 3. 变量的查找是就近原则去寻找,var定义的变量,当就近没有找到的话,就会查找外层
// 4. 当参数跟就近变量重名的时候,优先级是等同的

//引用类型与变量
var a = 5;
var b = a;
b += 3;
alert(a); //5

var a = [1,2,3];
var b = a;
b.push(4);
alert(a); //[1,2,3,4]

var a = [1,2,3];
var b = a;
b = [1,2,3,4];
alert(a); //[1,2,3]

//闭包题
var n=0;
function a(){
	var n=10;
	function b(){
		n++;
		alert(n);
	}
	b();//11
	return b;
}
var c= a();
c();//12
alert(n);//0

5&3   -->  1
5&&3  -->  3//取后者
5||3  -->  5//取前者

//正则中不常用的两个属性
//(?=) : 前向声明
//(?!) : 反前向声明
var str = 'abacad';
var re = /a(?=b)/g;//(?!b)返回的是ab@c@d
str = str.replace(re,'@');
console.log(str);//@bacad

//斐波那契数列
//递归
function aaa(n){
	if(n<=2){
		return 1;
	}
	return aaa(n-1) + aaa(n-2);
}
console.log(aaa(10));

//迭代
function bbb(n){
	var num1 = 1;
	var num2 = 1;
	var num3 = 0;

	for(var i=0; i<n-2; i++){
		num3 = num1+ num2;
		num1 = num2;
		num2 = num3;
	}

	return num3;
}
console.log(bbb(8));

//冒泡排序
function maopao(arr){
	for(var i=0; i<arr.length; i++){
		for(var j=0; j<arr.length-i; j++){
			toCon(j,j+1);
		}
	}

	function toCon(pre, nex){
		var tmp = '';
		if(arr[pre] > arr[nex]){
			tmp = arr[pre];
			arr[pre] = arr[nex];
			arr[nex] = tmp;
		}
	}

	return arr;
}
var arr = [4,2,1,5,7]
console.log(maopao(arr));

//选择排序
function xuanze(arr){

	if(arr.length == 1){
		return arr;
	}

	var iMin = arr[0];
	var iIndex = 0;

	for(var i=0; i<arr.length; i++){
		if(arr[i] < iMin){
			iMin = arr[i];
			iIndex = i;
		}
	}

	var pre = arr.splice(iIndex, 1);
	return pre.concat( xuanze(arr) );
}
var arr = [4,2,1,5,7]
console.log(xuanze(arr));

//数组去重
//方法一
function quchong(arr){
	var result = [arr[0]];

	for(var i=0; i<arr.length; i++){
		if(toCon(arr[i])){
			result.push(arr[i]);
		}
	}

	function toCon(val){
		for(var i=0; i<result.length; i++){
			if(result[i] == val){
				return false;
			}
		}
		return true;
	}

	return result;
}
var arr = [4,2,1,5,7,4,5,4,7,4];
console.log(quchong(arr));
//方法二
function quchong1(arr){
	var result = [];
	var obj = {};
	for(var i=0; i<arr.length; i++){
		if(!obj[arr[i]]){
			if(typeof arr[i] != 'object'){//过滤空对象
				result.push( arr[i] );
				obj[arr[i]] = 1;
			}
		}
	}

	return result;
}
var arr = [4,2,1,5,7,4,5,4,7,4];
console.log(quchong(arr));
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics