1.修改 this 指向
描述:
封装函数 f
,使 f
的 this
指向指定的对象
输入:bindThis(function(a, b){return this.test + a + b}, {test: 1})(2, 3)
function f(a, b) {
return this.test + a + b;
}
function bindThis(f, obj) {
//你实现的部分
}
//执行函数
var a = bindThis(f,{test:1});
a(2,3);
输出:6
我们可以观察到
1.
bindThis
这个函数接受两个参数,第一个参数为执行函数,第二个参数是要指定的对象。
2.
bindThis
函数返回一个匿名函数
实现:
function bindThis(f, oTarget) {//return function才会有a(2,3)
return function(){//slice是数组复制函数
var parames = Array.prototype.slice.call(arguments);//将类数组参数变成数组,将Array.prototype.slice的this指向arguments
return f.apply(oTarget,parames); //注意这里需要返回f的执行结果
}
}
2.URL相关
描述:
获取 url 中的参数
1. 指定参数名称,返回该参数的值 或者 空字符串
2. 不指定参数名称,返回全部的参数对象 或者 {}
3. 如果存在多个同名参数,则返回数组
输入:getUrlParam('http://www.nowcoder.com?key=1&key=2&key=3&test=4#hehe', 'key')
输出:['1', '2', '3']
实现:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp/exec
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;
}
}
3.dom 节点查找
描述:查找两个节点的最近的一个共同父节点,可以包括节点自身思路:
有两个dom的节点,dom1,dom21.判断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);
}
}
4.根据包名,在指定空间中创建对象
描述:
根据包名,在指定空间中创建对象 :
输入: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;
}
5.数组去重
题目描述
输入
[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a', 'a', NaN]
输出
[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a']
Array.prototype.uniq = function () {
var resArr = [];
var flag = true;
for(var i=0;i<this.length;i++){
if(resArr.indexOf(this[i]) == -1){ //this[i]是输入的数组,如果在resArr找不到该元素
if(this[i] != this[i]){ //排除 NaN
if(flag){
resArr.push(this[i]);
flag = false; //已经添加过一个NaN
}
}else{
resArr.push(this[i]);
}
}
}
return resArr;
}
只能检测三种类型的数组去重方法如下:
const arr = [ 1 , 1 , "haha" , "haha" , null];
let set = new Set(arr);
console.log(Array.from(set));
console.log([...set]);
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 星期五
实现:
8.字符串反转
var c = a.split("").reverse().join("");
字符串借用数组的方法:
var d = Array.prototype.map.call(a,function(v){
return v.toUpperCase()+".";
}).join(""):