目录:
1:call和apply方法调用
2:bind方法复制
3:函数中的几个属性值
4:高阶函数,函数作为参数
5:高阶函数,函数作为返回值。
6: 作用域链,作用域,预解析
1:call和apply方法调用
<script> function f1 (x, y) { console.log("结果是:"+(x+ y) + this); } // 函数的调用 f1(10, 20); console.log("==========="); //1: 此时的f1实际上是当成对象来使用的,对象可以调用方法,apply和call方法也是函数的调用的方式 f1.apply(); f1.call(); //2: apply和call都可以让函数或者方法来调用,传入参数和函数自己调用的写法不一样,但是效果是一样的, apply传入的是数组, call,传入的是参数 f1.apply(null, [100, 200]); f1.call(null, 100, 200); console.log("==========="); function f2(x, y){ console.log("这个函数是window对象的一个方法"+ (x+y) + this); console.dir(this); } window.f2(10, 20); var obj = { age: 10, name: "张三", } //3: apply和call可以改变this的指向, window.f2.call(obj, 10, 20); window.f2.apply(obj, [10,20]); // 4:apply和call方法实际上并不在函数这个实例对象中,而是在Function的prototype,原型对象中。
原型对象可以看成+方法,实例方法可以当成-方法。调用+方法时候可以当成对象。 console.log(f2.__proto__ == Function.prototype); console.log(Function.prototype); //{ [native code] } console.dir(Function); </script>
2:bind方法复制
<script> console.log("===== 11 =====") function f1 (x, y ){ console.log((x+y) + " :======>>>>"+this ); console.dir(this); } f1.bind(); // 方法复制了一份,并且传递参数,结果还是方法,方法没有调用。此时f1是对象。 // bind方法是复制的意思,可以在复制的时候传递参数,也可以在复制之后传递参数 // apply 和 call 是调用的时候改变this的指向 // bind是 复制的时候修改this的指向 var ff = f1.bind(null, 10, 20); console.log (ff); ff(); var f2 = f1.bind(null); f2(10, 20); console.log("===== 22 =====") // bind是方法复制,apply和call是方法调用 function Person (){ this.age = 10; } Person.prototype.eat = function () { console.log("这个是吃"); }; var per = new Person; var ff = f1.bind(per); ff(10, 20); console.log("===== 33 =====") function Person(age) { this.age = age; } Person.prototype.play = function () { console.log(this + "========>>>>" + this.age); } function Student (age) { this.age = age; } var per = new Person(10); var stu = new Student(20); var paly2 = per.play.bind(stu); paly2(); </script>
3: 函数中几个属性
<script> //函数中有一个name属性----->函数的名字,name属性是只读的,不能修改 //函数中有一个arguments属性--->实参的个数 //函数中有一个length属性---->函数定义的时候形参的个数 //函数中有一个caller属性---->调用(f1函数在f2函数中调用的,所以,此时调用者就是f2) function f1(x,y) { console.log(f1.name); console.log(f1.arguments.length); console.log(f1.length); console.log(f1.caller);//调用者 } f1.name="f5"; f1(10,20,30,40); console.dir(f1); function f2() { console.log("f2函数的代码"); f1(1,2); } f2(); </script>
4:高阶函数之参数是函数
<script> //fn是参数,最后作为函数使用了,函数是可以作为参数使用 function f1(fn) { console.log("f1的函数"); fn();//此时fn当成是一个函数来使用的 } //1: 传入匿名函数 f1(function () { console.log("我是匿名函数"); }); console.log("======= 22 ========"); // 命名函数 function f2() { console.log("f2的函数"); } // 2:传入的是命名函数 f1(f2); //函数作为参数的时候,如果是命名函数,那么只传入命名函数的名字,没有括号 </script>
5: 函数作为返回值
<script> console.log("======== 11 ========="); function f1() { console.log("f1函数的开始"); return function () { console.log("我是函数,但是我是我是我为函数的返回值"); }; // 我是不会执行的,因为此行代码上面有return console.log("f1函数的结束"); } var f2 = f1(); f2(); console.log("======== 22 ========="); var num=10; console.log(typeof num);//获取num这个变量的数据类型 var obj={};//对象 //判断这个对象是不是某个类型的 console.log(obj instanceof Object); //获取某个对象的数据类型的样子 //Object.prototype.toString.call(对象);//此时得到的就是这个对象的类型的样子 //此时输出的是Object的数据类型 [object Object] console.log(Object.prototype.toString()); //输出的数组的数据类型 [object Array] console.log(Object.prototype.toString.call([])); var arr=[10,20,30]; console.log(Object.prototype.toString.call(arr)); console.log("======== 33 ========="); //获取某个对象的类型是不是你传入的类型 //[10,20,30] 是不是"[object Array]" //type---是变量----是参数----"[object Array]" //obj---是变量-----是参数----[10,20,30]; //判断这个对象和传入的类型是不是同一个类型 function getFunc(type) { return function (obj) { return Object.prototype.toString.call(obj) === type; } } var ff = getFunc("[object Array]"); var result = ff([10, 20, 30]); console.log(result); var ff1 = getFunc("[object Object]"); var dt = new Date(); var result1 = ff1(dt); console.log(result1); </script>
6:作用域,作用域链,预解析
1:局部变量。函数中的变量是局部变量,外边无法访问。
2:预解析:变量的声明,和函数的声明提前
<script> // 变量---->局部变量和全局变量, // 作用域:就是变量的使用范围 // 局部作用域和全局作用域 // js中没有块级作用域---一对括号中定义的变量,这个变量可以在大括号外面使用 // 函数中定义的变量是局部变量 while(true){ var num=10; break; } console.log(num); { var num2=100; } console.log(num2); if(true){ var num3=1000; } console.log(num3); function f1() { //局部变量 var num1=10; } // console.log(num1); console.log("======== 22 ======"); // 作用域链:变量的使用,从里向外,层层的搜索,搜索到了就可以直接使用了 // 层层搜索,搜索到0级作用域的时候,如果还是没有找到这个变量,结果就是报错 var num=10; //作用域链 级别:0 var num2=20; var str = "abc" function f1() { var num2=20; function f2() { var num3=30; console.log(num); } f2(); } f1(); //预解析:就是在浏览器解析代码之前,把变量的声明和函数的声明提前(提升)到该作用域的最上面 //变量的提升 console.log(num); var num=100; //函数的声明被提前了 f1(); function f1() { console.log("这个函数,执行了"); } var f2; f2=function () { console.log("小杨好帅哦"); }; f2(); </script>