一、原生js实现Bind
bind的三个特点
(1)保存this,返回新的函数
(2)可以传入参数
(3)一个绑定函数也可以使用new操作符创建对象,这种行为就像把原函数当成构造器,提供的this值被忽略,同时调用时的参数被提供给模拟函数
根据三个特点,分为3个步骤来实现bind
(1)保存this,返回新的函数
var foo={
value:1
};
function bar(){
console.log(this.value)
}
Function.prototype.bind0=function(context){
var self=this;
console.log(self);//在这里this是bar
return function(){
self.apply(context) //执行bar()函数把里面的this 换为context的值
}
}
//使用bind
bar.bind(foo)();
//使用自己的Bind0
bar.bind0(foo)();
输出结果
自己实现的Bind也输出了1,并且保存的this值为Bar().context 为foo, self.apply(context)即执行bar函数,并把this 改为foo, this.value===foo.value,输出值为1
(2)可以传入参数
function bar(name,age){
console.log(name);
console.log(age);
console.log(this.value)
}
Function.prototype.bind0=function(context){
var self=this;
// console.log(self);//在这里this是bar
var args=Array.prototype.slice.call(arguments,1);
return function(){
var args1=Array.prototype.slice.call(arguments,0);
self.apply(context,args.concat(args1)) //执行bar()函数把里面的this 换为context的值
}
}
//使用bind
bar.bind(foo,"lily")(36);
bar.bind(foo,"lily",36)();
//使用自己的Bind0
bar.bind0(foo,"lily")(36);
bar.bind0(foo,"lily",36)();
输出结果:
分析:
var args=Array.prototype.slice.call(arguments,1);
slice()方法数组和字符串也有,都是截取字符串或者数组,本次选用数组的slice 。运用call方法把slice的this值变为类数组arguments,arrayObj.slice(start, [end]),这里的第二个参数1,即为给slice传入的参数,即从下标截取到结束。
本题即为除保存的this值外传入的其他参数。
args1是是bind返回的函数结束的参数,所以直接从0开始截取。
(3)一个绑定函数也可以使用new操作符创建对象,这种行为就像把原函数当成构造器,提供的this值被忽略,同时调用时的参数被提供给模拟函数
传入的参数依然接收,但是this值并没有改变,所以this.value输出undefined
Function.prototype.bind0=function(context){
var self=this;
var args=Array.prototype.slice.call(arguments,1);
var fResult= function(){
console.log(this);//没有fResult接收匿名函数时,这个this这是一个空对象,如果把这里面的this 变为bar ,则可以实现obj1.sex为女this
console.log(self);
var args1=Array.prototype.slice.call(arguments,0);
self.apply(this instanceof self?this:context,args.concat(args1));//函数把里面的this 换为context的值
};
fResult.prototype=self.prototype;
return fResult;
} //使用bind
var bindfoo= bar.bind(foo,"lily");
var obj=new bindfoo(36);
console.log(obj.sex)
//使用自己的Bind0
var bindfoo1= bar.bind0(foo,"lily");
var obj1=new bindfoo1(36);
console.log(obj1.sex)
输出结果:
分析:主要添加的this的判别, this是bar()函数的实例,则具备bar对象的原型,如果不是则依旧传入context
二、零碎知识点总结
1、判断一个字符串中是否有汉字
(1)用正则表达式判断
var reg = new RegExp("[\\u4E00-\\u9FFF]+","g");
(2)JavaScript charCodeAt() 方法
charCodeAt() 方法可返回指定位置的字符的 Unicode 编码。这个返回值是 0 - 65535 之间的整数。如果大于255,则是汉字。
语法: stringObject.charCodeAt(index)
例题:如果第二个参数 bUnicode255For1 === true,则所有字符长度为 1
否则如果字符 Unicode 编码 > 255 则长度为 2
function strLength(s, bUnicode255For1) {
if(!bUnicode255For1){
var strlen=0;
for(var i = 0;i < s.length; i++){
if(s.charCodeAt(i) > 255){ //如果是汉字,则字符串长度加2
strlen += 2}
else
{strlen++;}
}
return strlen; }
else{ return s.length; }
}
2、字符串和数组的方法区别
字符串常用方法:
名称 | 语法 | 返回值 |
slice | slice(start,end) | 提取字符串的片断,并在新的字符串中返回被提取的部分。 |
split | split(",") | 把字符串分割为字符串数组。 |
substr | substr(index,len) | 从指定位置开始截取给定长度的字符串,返回此新的字符串,如果没有指定 length,那么返回的字符串包含从 start 到 stringObject 的结尾的字符。 |
substring | substring(start,end) | 截取子字符串 |
concat | | 连接字符串,返回连接后的字符串 |
结论:上述字符串方法均不改变原字符串
数组常用方法
名称 | 语法 | 返回值 |
concat | | concat() 方法用于连接两个或多个数组。 该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。 |
pop | pop() | 删除并返回数组的最后一个元素 |
push | | 向数组中压入数据,返回新数组的长度 |
slice | | 从某个已有数组中返回选定的元素 |
splice | | 从数组中添加或删除项目,返回被删除的项目 |
结论:数组concat方法不改变原数组,Push和pop的返回值分别为新数组的长度和删除的元素,改变了原数组。(补充:shift也会改变原数组)
slice不改变原数组,splice增加时不返回元素,替换时返回替换的元素,并且改变原数组
3、用户输入内容,检测和json数据中的某一项是否对应。
<ul id="list">
<li id="code0"><span>Course Code</span><input class="code0" placeholder="Please enter your Course code"></li>
<li id="code1"><span>Course Code</span><input class="code1" placeholder="Please enter your Course code"></li>
<li id="code2"><span>Course Code</span><input class="code2" placeholder="Please enter your Course code"></li>
<li id="code3"><span>Course Code</span><input class="code3" placeholder="Please enter your Course code"></li>
<li id="code4"><span>Course Code</span><input class="code4" placeholder="Please enter your Course code"></li>
</ul>
在输入enter键时候,判断判断所填入内容和json内容sh是否一致
var database0 = [{
Coursecode: "WEB122",
Coursetitle: "Intro to programming",
Credit: 3
},
{
Coursecode: "WEB222",
Coursetitle: "Web Programming Principles",
Credit: 3
},
{
Coursecode: "WEB322",
Coursetitle: "Object Oriented Programming",
Credit: 3
},
{
Coursecode: "WEB422",
Coursetitle: "Principles",
Credit: 3
},
{
Coursecode: "WEB522",
Coursetitle: "Math",
Credit: 3
},
];
var course = document.getElementById("list")
course.onkeyup=function(e){
console.log(e.target);
var keyNum=window.event ? e.keyCode :e.which;
//判断如果用户按下了回车键(keycode=13)
if(keyNum==13){
var num = e.target.value;
for(var i=0;i<database0.length;i++){
if(database0[i].Coursecode==num){
console.log(num)
return ;
}else{ }
}
alert("Please re-enter a valid course code")
}else{
}
};
用户按下enter键,会判断是否一致,出现问题,如果一致,会弹出4次不一致,一次无反应。检查后发现,alert不应该写在for循环的里面,而应该写在外面。