高级函数
//函数安全
//防止忘记使用new后,this指向window
function person(name,age,job){
if(this instanceof person){
this.name=name;
this.age=age;
this.job=job;
}else{
return new person(name,age,job);
}
}
//构造函数窃取其他构造函数 寄生组合继承
function one (side){
this.side=side;
}
function two (width){
one.call(this,2);//this指向pllygon ,side=2 第二次调用
this.width=width;
}
two.prototype = new one();//第一次调用 不加这句结果undefine
three=new two(4);
alert(three.side);//2
//大量if,可以使用惰性载入函数提升效率
//方法一 在调用函数是在处理函数 ,该函数会被覆盖为另一个按合适方式执行的函数
function creatXHR (){//ajax创建XHR对象
if(typeof XMLHttpRequest ! = "undefine"){
creatXHR=function(){
return new XMLHttpRequest();
};
}
else if (typeof ActiveXObject ! = "undefine"){
creatXHR=function(){
if (typeof arguments.callee.activeXString ! = "string") {
var versions=["MSXML2.XMLHttp.6.0","MSXML2.XMLHttp.3.0",
"MSXML2.XMLHttp"],i,len;
for(i=0,len=versions.length;i<len;i++){
try{
new ActiveXObject(versions[i]);
arguments.callee.activeXString=versions[i];
break;
}
catch(ex){
}
}
return new ActiveXObject(arguments.callee.activeXString);
};
}
else{
creatXHR=function(){
throw new Error("No XHR object available.")
}
}
}
return creatXHR();
}
//方法二
var detection = (function(){
if(//支持某特性){
return function(){
//直接用支持的特性
}
} else if(//支持第二种特性){
return function(){
//用第二种特性
}
} else {
return function(){
//用其他解决方案
}
}
})();
//函数绑定
//可以在特定的this环境中以指定的参数调用另一个函数
function bind(fn,context){//fn 函数 context 环境
return function () {
return fn.apply(context,arguments); //arguments fn的参数
};
}
//es5有bind 可直接使用fn.bind(context)
bind(fn,context);
//函数柯里化
//用于设置一个或多个参数的函数
function curry (fn) {
var args=Array.prototype.slice.call(arguments,1);//arguments curry的参数
//截取 fn 函数出去,只剩除fn之外的参数
//因为arguments并不是真正的数组对象,只是与数组类似而已,
//所以它并没有slice这个方法,而Array.prototype.slice.call(arguments, 1)
//可以理解成是让arguments转换成一个数组对象,让arguments具有slice()方法。
return function () {
var innerArgs=Array.prototype.slice.call(arguments);
var finalArgs=args.concat(innerArgs); //将传递的参数拼接成新数组,并返回新数组
return fn.apply(null,finalArgs);//没有考虑运行环境,所以第一个参数为null
}
}
//更复杂的bind
function bind(fn,context){//fn 函数 context 环境
var args=Array.prototype.slice.call(arguments,2);
return function () {
var innerArgs=Array.prototype.slice.call(arguments);
var finalArgs=args.concat(innerArgs); //将传递的参数拼接成新数组,并返回新数组
return fn.apply(context,finalArgs); //arguments 参数
};
}
//去抖函数 函数节流
function debounce (fn,wait){
var td;
return function () {
clearTimeout(td);
td=setTimeout(fn,wait)
}
}
var myfunc = debounce(function () {
//繁重,消耗性能的操作
},250);
window.addEventListener(‘resize’,myfunc);
/*
像窗口的resize,这类可以以较高的速率触发的事件,非常适合用去抖函数,这时
也可称作“函数节流”,避免给浏览器带来过大的性能负担。
具体的实现时,当函数被调用时,不立即执行相应的语句,
而是等待固定的时间w,若在w时间内,即等待还未结束时,
函数又被调用了一次,则再等待w时间,
重复上述过程,直到最后一次被调用后的w时间内该函数都没有被再调用,
*/
//顾名思义,once函数是仅仅会被执行一次的函数
function once (fn) {
var result;
return function () {
if(fn){
result=fn(arguments);
fn=null;
}
return result;
}
}
var init =once(function(){
//初始化操作
})
//Array是一个类 ,slice是一个方法 call
function test(a,b,c,d)
{
var arg = Array.prototype.slice.call(arguments,1);
alert(arg);
}
test(“a”,“b”,“c”,“d”); //b,c,d
//在没有默认值时,fn.length指的是形参的个数,如果有参数有默认值,
//那么就取第一个具有默认值之前的参数的个数。
//形参个数
function a(x,y){}
a.length // 2
function b(x,y=2,z){}
b.length // 1
function c(x,…args){}
c.length //1
//在函数内部使用,表示实际传入的参数个数,在运行时计算,和形参个数无关
function a(x,y,z){
console.log(arguments.length); // 3
}(1,2,3)
function b(x,y=2){
console.log(arguments.length) // 3
}(1,2,3)
function c(x,y=2){
console.log(arguments.length) // 1
}
//我们知道,Array.prototype.slice.call(arguments)
//能将具有length属性的对象转成数组,除了IE下的节点集合
//(因为ie下的dom对象是以com对象的形式实现的,js对象与com对象不能进行转换)
//如:
var a={length:2,0:‘first’,1:‘second’};
Array.prototype.slice.call(a);// [“first”, “second”]
var a={length:2};
Array.prototype.slice.call(a);// [undefined, undefined]
//实例,正则使用
function curry(fn){
var i = 0;
var outer = Array.prototype.slice.call(arguments,1);
console.log(outer)
var len = fn.length;
return function(){
var inner = outer.concat(Array.prototype.slice.call(arguments));
return inner.length === len?fn.apply(null,inner):function (){
var finalArgs = inner.concat(Array.prototype.slice.call(arguments));
return fn.apply(null,finalArgs);
}
}
}
var match = curry(function(what,str){
return str.match(what)
});
var hasNumber = match(/[0-9]+/g);
var hasSpace = match(/\s+/g)
hasNumber(“123asd”); //[‘123’]
hasNumber(“hello world!”); //null
hasSpace(“hello world!”); //[’ '];
hasSpace(“hello”); //null
console.log(match(/\s+/g,‘i am Claiyre’)); //直接全部传参也可: [’ ‘,’ ']
//高级函数只是参数是函数或者返回值是函数
var Moqi = function(p1){
this.add = function (p2){
return p1 + ’ ’ + p2;
};
return add;
};
var m=moqi(‘hello’);//m是一个函数 moqi(‘hello’)
//返回的是
//function (p2) {
// return ‘p1’ + ’ ’ + ‘p2’;
//}
m(‘world’);//结果为 hello world
/*
这里的m如何知道p1的值,p1是函数的全局变量
function (p2){
return p1 + ’ ’ + p2;
};
*/
//call apply this 的理解
var age = 40;
var xiaoMing = {
age:30
};
var xiaoLi = {
age: 20
};
var getAge = function(){
console.log(this.age);
};
getAge.call( xiaoMing ); //30 表示函数this指向xiaoMing
getAge.call(xiaoLi); //20 表示函数this指向xiaoLi
getAge.call(undefined);//40
getAge.call(undefined)==getAge.call(null)
getAge.call(null);//40
getAge(); //40
function Class1()
{
this.name = “class1”;
this.showNam = function()
{
alert(this.name);
}
}
function Class2()
{
this.name = “class2”;
}
var c1 = new Class1();
var c2 = new Class2();
c1.showNam.call(c2);
/Class2 就继承Class1了,Class1.call(this) 的 意思就是使用 Class1 对象
代替this,那么 Class2 中不就有Class1 的所有属性和方法了吗,c2 对象
就能够直接调用Class1 的方法以及属性了/
function Class1()
{
this.showTxt = function(txt)
{
alert(txt);
}
}
function Class2()
{
Class1.call(this);
}
var c2 = new Class2();
c2.showTxt(“cc”);
//多重继承
function Class10()
{
this.showSub = function(a,b)
{
alert(a-b);
}
}
function Class11()
{
this.showAdd = function(a,b)
{
alert(a+b);
}
}
function Class2()
{
Class10.call(this);
Class11.call(this);
}
本文深入探讨JavaScript中的高级函数概念,包括函数安全、构造函数继承、惰性加载、函数绑定、柯里化、去抖与节流等技巧,以及如何在特定环境中调用函数和处理参数。通过实例演示,帮助读者掌握这些高级函数的应用场景和实现方式。

1万+

被折叠的 条评论
为什么被折叠?



