🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] **** ## 1 函数声明与表达式 ## 2 函数的调用 ###1 f() 直接调用函数 ###2 f.call(obj,a1,a2..) obj作为函数体内this的指向对象 a1,a2,..等作为函数的参数 call()方法使用一个指定的this值和若干个指定的参数调用函数或方法。 调用一个函数,可以使用不同的this对象。即call方法的第一个参数 通过call方法,可以在一个对象上调用另一个对象的方法。 `fun.call(thisArg[,arg1[,arg2[,....]]])` > thisArg 1 为空,或者null,undefined,函数中的this指向window对象 2 值为数字字符串布尔值会自动包装为对象 3 传递另一个函数名,this指向函数的引用。 4 传递一个对象 则指向这个对象 > arg1,arg2.... 参数列表 例子1 ~~~ function a(){ //输出函数a中的this对象 console.log(this); } //定义函数b function b(){} //定义对象obj var obj = {name:'test'}; a.call(); //window a.call(null); //window a.call(undefined);//window a.call(1); //Number a.call(''); //String a.call(true); //Boolean a.call(b);// function b(){} a.call(obj); //Object ~~~ 例子2 ~~~ function greet() { var reply = [this.person, '是一个轻量的', this.role].join(' '); console.log(reply); } var i = { person: 'JSLite.io', role: 'Javascript 库。' }; greet.call(i); // JSLite.io 是一个轻量的 Javascript 库。 ~~~ 例子3 ~~~ var animals = [ {species: 'Lion', name: 'King'}, {species: 'Whale', name: 'Fail'} ]; for (var i = 0; i < animals.length; i++) { (function (i) { this.print = function () { console.log('#' + i + ' ' + this.species + ': ' + this.name); } this.print(); }).call(animals[i], i); } //#0 Lion: King //#1 Whale: Fail ~~~ 例子4 ~~~ var a = { name:'JSLite.io', //定义a的属性 say:function(){ //定义a的方法 console.log("Hi,I'm function a!"); } }; function b(name){ console.log("Post params: "+ name); console.log("I'm "+ this.name); this.say(); } b.call(a,'test'); //Post params: test //I'm onepixel //I'm function a! ~~~ ###3 f.apply(obj,[]) obj作为函数体内this的指向对象 []作为函数的参数数组。 与call基本相同,区别在于参数列表以数组形式表示。 `fun.apply(thisArg[,argsArrat])` 例子1 ~~~~ function jsy(x,y,z){ console.log(x,y,z); } jsy.apply(null,[1,2,3]); // 1 2 3 ~~~~ 例子2 ~~~~ Function.prototype.construct = function(aArgs) { var fConstructor = this, fNewConstr = function() { fConstructor.apply(this, aArgs); }; fNewConstr.prototype = fConstructor.prototype; return new fNewConstr(); }; function MyConstructor () { for (var nProp = 0; nProp < arguments.length; nProp++) { console.log(arguments,this) this["property" + nProp] = arguments[nProp]; } } var myArray = [4, "Hello world!", false]; var myInstance = MyConstructor.construct(myArray); console.log(myInstance.property1); // logs "Hello world!" console.log(myInstance instanceof MyConstructor); // logs "true" console.log(myInstance.constructor); // logs "MyConstructor" ~~~ ## 3 函数的属性 ## 4 函数的方法 ## 5 闭包的使用 ## 6 函数的创建 ###1 bind() bind()函数会创建一个新函数 > 1 es5新增的一个方法 2 传参和call或者apply类似 3 不会执行对应的函数,call或apply则自动执行对应的函数 4 返回对函数的引用 `fun.bind(thisArg[,arg1[,arg2[,....]]])` 例子1 ~~~ var obj = {name:'JSLite.io'}; /** * 给document添加click事件监听,并绑定EventClick函数 * 通过bind方法设置EventClick的this为obj,并传递参数p1,p2 */ document.addEventListener('click', EventClick.bind(obj,'p1','p2'),false); //当点击网页时触发并执行 function EventClick(a,b){ console.log( this.name, //JSLite.io a, //p1 b //p2 ) } // JSLite.io p1 p2 ~~~ 兼容实现 ~~~ if (!Function.prototype.bind) { Function.prototype.bind = function (oThis) { if (typeof this !== "function") { // closest thing possible to the ECMAScript 5 // internal IsCallable function throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, // this在这里指向的是目标函数 fNOP = function () {}, fBound = function () { return fToBind.apply(this instanceof fNOP ? this //此时的this就是new出的obj : oThis || this,//如果传递的oThis无效,就将fBound的调用者作为this //将通过bind传递的参数和调用时传递的参数进行合并,并作为最终的参数传递 aArgs.concat(Array.prototype.slice.call(arguments))); }; fNOP.prototype = this.prototype; //将目标函数的原型对象拷贝到新函数中,因为目标函数有可能被当作构造函数使用 fBound.prototype = new fNOP(); //返回fBond的引用,由外部按需调用 return fBound; }; } ~~~ 应用例子 继承 ~~~ function Animal(name,weight){ this.name = name; this.weight = weight; } function Cat(){ // 在call中将this作为thisArgs参数传递 // Animal方法中的this就指向了Cat中的this // 所以Animal中的this指向的就是cat对象 // 在Animal中定义了name和weight属性,就相当于在cat中定义了这些属性 // cat对象便拥有了Animal中定义的属性,从而达到了继承的目的 Animal.call(this,'cat','50'); //Animal.apply(this,['cat','50']); this.say = function(){ console.log("I am " + this.name+",my weight is " + this.weight); } } //当通过new运算符产生了cat时,Cat中的this就指向了cat对象 var cat = new Cat(); cat.say(); //输出=> I am cat,my weight is 50 ~~~ 原型扩展 ~~~ function test(){ // 检测arguments是否为Array的实例 console.log( arguments instanceof Array, //false Array.isArray(arguments) //false ); // 判断arguments是否有forEach方法 console.log(arguments.forEach); // undefined // 将数组中的forEach应用到arguments上 Array.prototype.forEach.call(arguments,function(item){ console.log(item); // 1 2 3 4 }); } test(1,2,3,4); ~~~ ## 6 参考链接 [重读javascript的Function](https://segmentfault.com/a/1190000004252024) [回味js基础,call apply bind](https://segmentfault.com/a/1190000004568767)