[ 问题演习 ] 前端妙技演习1

问题泉源:http://www.nowcoder.com/ta/front-end

1.数组去重

1.两个轮回:

思绪: 新建一个新数组用于寄存反复的数组元素,经由过程两个轮回,比较两个数组元素是不是雷同。外轮回掌握第一个比较元素,内轮回掌握第二个比较元素,假如有反复元素则将该元素添加到新数组中,末了返回这个新数组。
完成:

Array.prototype.distinct = function() {
    var ret = [];
    for (var i = 0; i < this.length; i++)
    {
        for (var j = i+1; j < this.length;) {   
            if (this[i] === this[j]) {
                ret.push(this.splice(j, 1)[0]);
            } else {
                j++;
            }
        }
    }
     return ret;
};
//for test
alert(['a','b','c','d','b','a','e'].distinct());

2.一次轮回

思绪:建立一个空对象的和空数组,经由过程轮回,将原数组中的每一个元素的值作为键值对添加到控对象中,假如这个对象中已存在该属性,则申明这个数组元素是反复的,则将他添加到空数组中,末了返回新建立的数组。
完成:

Array.prototype.distinct=function(){
    var arr=[];
    var obj={};
    for(var i=0;i<this.length;i++){
        if(obj[this[i]]==undefined)
            obj[this[i]]=this[i];
        else if(obj[this[i]])
            arr.push(this[i]);
    }
    return arr;
 }
alert(['a','b','c','d','b','a','e'].distinct());  

2.dom 节点查找

形貌:查找两个节点的近来的一个共同父节点,能够包括节点本身
思绪:

有两个dom的节点,dom1,dom2
1.推断dom1节点是不是包括dom2节点;包括则返回dom1,不包括继承向下运转;
2.推断dom2节点是不是包括dom1节点;包括则返回dom2,不包括继承向下运转;
3.经由过程个中一个节点dom1去猎取该节点的父节点,dom_p;
4.经由过程父节点dom_p去查dom_f的子节点,看dom2是不是在父节点dom_f的子节点中;
5.假如dom2在dom_f的子节点中,则dom_f是近来的父节点;
6.如dom2不在dom_f的子节点中,则以domf_f继承去查dom_f的父节点,反复1,2,3,4步骤终究得出父节点dom_f

完成1:

function commonParentNode(oNode1, oNode2) {
    if(oNode1.contains(oNode2)){
        return oNode1;
    }else if(oNode2.contains(oNode1)){
        return oNode2;
    }else{
        return commonParentNode(oNode1.parentNode,oNode2);
    }
}

完成2:

function commonParentNode(oNode1, oNode2) {
    if(oNode2.contains(oNode1)) return oNode2;
    while(oNode1) {
        if(oNode1.contains(oNode2)){
            return oNode1;
        }
        oNode1 = oNode1.parentNode;
    }
}

3.URL相干

形貌:

猎取 url 中的参数
1. 指定参数称号,返回该参数的值 或许 空字符串
2. 不指定参数称号,返回悉数的参数对象 或许 {}
3. 假如存在多个同名参数,则返回数组
输入:
getUrlParam('http://www.nowcoder.com?key=1&key=2&key=3&test=4#hehe', 'key')

输出:
['1', '2', '3']

完成:

function getUrlParam(sUrl, sKey) {

    var r = [] , s = null  , i = 0;
    var regexp = new RegExp(/[?&]([\w]*)=([^&#]*)/g);

    while((s = regexp.exec(sUrl)) != null){
        if(!r[s[1]])r[s[1]] = s[2];
        else if(typeof(r[s[1]]) == 'object'){
            r[s[1]].push(s[2]);
        }else{
            r[s[1]] = [r[s[1]],s[2]];
        }
    }
    if(sKey){
        //有参数,返回参数值或空
        if(r[sKey]){
            return r[sKey];
        }else{
            return '';
        }
    }else{
        return r;
    }
}

扩大:

1.window.location属性相干:

  • 设置或猎取对象指定的文件名或途径。
    alert(window.location.pathname);

  • 设置或猎取全部 URL 为字符串。
    alert(window.location.href);

  • 设置或猎取与 URL 关联的端口号码。
    alert(window.location.port);

  • 设置或猎取 URL 的协定部份。
    alert(window.location.protocol);

  • 设置或猎取 href 属性中在井号“#”背面的分段。
    alert(window.location.hash);

  • 设置或猎取 location 或 URL 的 hostname 和 port 号码。
    alert(window.location.host);

  • 设置或猎取 href 属性中跟在问号背面的部份。
    alert(window.location.search);

2.其他的猎取url参数的要领:

体式格局一:只能对牢固url举行操纵,返回悉数参数

function GetRequest() {
var url = location.search; //猎取url中"?"符后的字串
var theRequest = new Object();
if (url.indexOf("?") != -1) {
  var str = url.substr(1);
  strs = str.split("&");
  for(var i = 0; i < strs.length; i ++) {
     theRequest[strs[i].split("=")[0]]=(strs[i].split("=")[1]);
  }
}
 return theRequest;
}

体式格局二:正则表达式体式格局,只能对牢固url操纵,返回指定参数

function GetQueryString(name) {
   var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)","i");
   var r = window.location.search.substr(1).match(reg);
   if (r!=null) return (r[2]); return null;
}

体式格局三:对恣意的url操纵,返回指定数目的参数

function getUrlParames(url,keys){

    var request = {},
        result,
        parameStr = '',
        parames = [],
        keyValue = [],
        index = url.indexOf('?');

    if (index) {
        parameStr = url.substr(index+1);
        parames = parameStr.split("&");
        for(var i = 0, lng = parames.length; i < lng; i ++) {
            keyValue = parames[i].split("=");
            request[keyValue[0]] = keyValue[1];
      }
    }

    if (typeof keys == 'string') {
        result = request[keys];
    }else if(!keys){
        return request;
    }
    else{

        result = {};
        for(var j = 0,lng = keys.length;j < lng;j++){
            result[keys[j]] = request[keys[j]];
        }
    }

    return result;
}

4:修正 this 指向

形貌:
封装函数 f,使 fthis 指向指定的对象
输入:bindThis(function(a, b){return this.test + a + b}, {test: 1})(2, 3)
输出:6
思绪:
我们能够观察到
1.bindThis这个函数接收两个参数,第一个参数为实行函数,第二个参数是要指定的对象。
2.bindThis函数返回一个匿名函数

完成:

function bindThis(f, oTarget) {
    return function(){
        var parames = Array.prototype.slice.call(arguments);
        return f.apply(oTarget,parames); //注重这里须要返回f的实行效果
    }
}

5.依据包名,在指定空间中建立对象

形貌:
依据包名,在指定空间中建立对象 :
输入:namespace({a: {test: 1, b: 2}}, 'a.b.c.d')
输出:{a: {test: 1, b: {c: {d: {}}}}}

思绪:
namespace函数的第一个参数是原始对象,第二个参数是须要建立的对象的包括关联。
经由过程输出效果能够看出,假如第二个参数中的对象在原始对象中存在并且是它的值为一个对象则不做转变,若不为对象,则从新赋值为空对象{}.

完成:

function namespace(oNamespace, sPackage) {

    var properties = sPackage.split('.');
    var parent = oNamespace;

    for (var i = 0, lng = properties.length; i < lng; ++i) {

        var property = properties[i];

        if (Object.prototype.toString.call(parent[property])!== '[object Object]') {
            parent[property] = {};
        }

        parent = parent[property];

    }

    return oNamespace;

}

6.斐波那契数列

形貌:

什么是斐波那契数列:1,1,2,3,5….n 。很轻易看出规律,从第三个数字最先,每一个数字即是前两个数字之和。

思绪:

1.前两个数字都为 1
2.运用递归

完成:

function fibonacci(n) {
    if(n ==1 || n == 2){
        return 1
    }
    return fibonacci(n - 1) + fibonacci(n - 2);
}

7.时候花样化输出

形貌:

按所给的时候花样输出指定的时候
花样申明
关于 2014.09.05 13:14:20
yyyy: 年份,2014
yy: 年份,14
MM: 月份,补满两位,09
M: 月份, 9
dd: 日期,补满两位,05
d: 日期, 5
HH: 24制小时,补满两位,13
H: 24制小时,13
hh: 12制小时,补满两位,01
h: 12制小时,1
mm: 分钟,补满两位,14
m: 分钟,14
ss: 秒,补满两位,20
s: 秒,20
w: 礼拜,为 [‘日’, ‘一’, ‘二’, ‘三’, ‘四’, ‘五’, ‘六’] 中的某一个,本 demo 效果为 五
输入例子:
formatDate(new Date(1409894060000), ‘yyyy-MM-dd HH:mm:ss 礼拜w’)

输出例子:
2014-09-05 13:14:20 礼拜五

完成:

function formatDate(oDate, sFormation) {
    var obj = {
        yyyy:oDate.getFullYear(),
        yy:(""+ oDate.getFullYear()).slice(-2),//异常精炼的要领
        M:oDate.getMonth()+1,
        MM:("0"+ (oDate.getMonth()+1)).slice(-2),
        d:oDate.getDate(),
        dd:("0" + oDate.getDate()).slice(-2),
        H:oDate.getHours(),
        HH:("0" + oDate.getHours()).slice(-2),
        h:oDate.getHours() % 12,
        hh:("0"+oDate.getHours() % 12).slice(-2),
        m:oDate.getMinutes(),
        mm:("0" + oDate.getMinutes()).slice(-2),
        s:oDate.getSeconds(),
        ss:("0" + oDate.getSeconds()).slice(-2),
        w:['日', '一', '二', '三', '四', '五', '六'][oDate.getDay()]
    };
    return sFormation.replace(/([a-z]+)/ig,function($1){return obj[$1]});
}

8.猎取字符串的长度

形貌:

假如第二个参数 bUnicode255For1 === true,则一切字符长度为 1
不然假如字符 Unicode 编码 > 255 则长度为 2
输入例子:

strLength('hello world, 牛客', false)

输出例子:
17

完成:

function strLength(s, bUnicode255For1) {

    if(bUnicode255For1) return s.length;

    var length = s.length;
    for(var i = 0, lng = length; i < lng; i++){
        if(s.charCodeAt(i)>255){
            length ++;
        }
    }
    return length;
}

9.邮箱字符串推断

形貌:

推断输入是不是是准确的邮箱花样
输入: 邮箱字符串
输出: true示意花样准确,false示意毛病

完成:

function isAvailableEmail(sEmail) {
    var parter = /^[a-z0-9_+.-]+\@([a-z0-9-]+\.)+[a-z0-9]{2,4}$/;
    return parter.test(sEmail);
}

这题的关键是明白这个正则表达式,我们拆开来看看:

1.^[a-z0-9_+.-]+ : 这个示意以一个或多个小写字母,数字或_,+,.,-这几个个字符开首

2.\@([a-z0-9-]+\.)+ : 这个示意1中的字符连着@,背面再接着一个多个由小写字母,数字,-字符和点.的构成的字符串。

3.[a-z0-9]{2,4}$ 这个比较简单,示意以长度为2-4的,由小写字母和数字恣意组合构成的字符串末端。

    原文作者:kraaas
    原文地址: https://segmentfault.com/a/1190000002976199
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞