call( ), apply( ), bind( )方法

1. call( ), apply( ) 实现间接调用函数:

Function.call( obj, param1, param2,… );
Function.apply( obj, args );

这两个方法都是显式的指定要调用的this值, 即obj可以调用不是自身的方法里的那个函数. 也就是说, 任何函数可以被任何对象的方法来调用. 不同的只是所传入的第二个参数, apply( ) 是直接填入数组. Math.max( ) 和 Math.min( ) 里必须传入具体的值, 数组却没有找出最大最小值的方法, 怎么办?就用 call( ), apply( ) 来实现间接调用, 这时的 obj 使用 Math 和 null 都可以. var arr = [32, 5, -8, 110, 76, -0.5, -11]; var max = Math.max.apply(Math, arr), min = Math.min.apply(null, arr); console.log(max, min); // 110, -11 var a1 = [1, 2, 3], a2 = [4, 5, 6]; Array.prototype.push.apply(a1, a2); console.log(a1); // [1, 2, 3, 4, 5, 6] var arr = ['you', 'banana']; console.log(String.prototype.substr.apply(arr, [1, 6])); // ou,ban 调用别人家的函数: 对象 a 没有 mean( ) 方法, 所以 console.log( a.mean( ) ) 会打印出错误. 但如果我认为不需要重写 a, 为它增加方法而改变它的结构, 或者 mean( ) 函数可以被众多对象调用时, 就可以采用 mean.call(a, ...); function mean(){ var sum = 0; for(var i = 0; i < arguments.length; i++){ sum += arguments[i]; } sum += this.max + this.min; return sum / (arguments.length + 2); } var a = { max: 100, min: 45 }, m = mean.call(a, 27, 89, 30, 61); console.log(a.mean()); // TypeError: a.mean is not a function console.log(m); // 58.666666...

2. 判断类型 console.log(Object.prototype.toString.call(123)); // [object Number] console.log(typeof 123); // number console.log(Object.prototype.toString.call('123')); // [object String] console.log(typeof '123'); // string console.log(Object.prototype.toString.call(undefined)); // [object Undefined] console.log(typeof undefined); // undefined console.log(Object.prototype.toString.call(true)); // [object Boolean] console.log(typeof true); // boolean console.log(Object.prototype.toString.call({})); // [object Object] console.log(typeof {}); // object console.log(Object.prototype.toString.call([])); // [object Array] console.log(typeof []); // object console.log(Object.prototype.toString.call(function(){})); // [object Function] console.log(typeof function(){}); // function

3. 实现继承:
Animal.call( this, name ) 使得 Cat 拥有了 Animal 的属性和方法, 此时的 this 指代 Cat, 它可以调用 speak( )函数. Parent.call( child ) 让 child 继承了 Parent, 自动拥有了 name 和 age 属性, 当然可以对这两个属性重新赋值. Object3D.call( this ) 则表明网格 Mesh 是继承于 Object3D 的. function Animal(name){ this.name = name; this.speak = function(){ console.log('My name is ' + this.name); } } function Cat(name){ Animal.call(this, name); } var c = new Cat('Mimi'); c.speak(); // My name is Mimi var Parent = function(){ this.name = "Web Front"; this.age = 22; }; var child = {}; Parent.call(child); console.log(child); child.name = "WebGL"; child.age = 10; console.log(child); function Object3D() { Object.defineProperty( this, 'id', { value: object3DId ++ } ); this.uuid = _Math.generateUUID(); this.name = ''; this.type = 'Object3D'; this.parent = null; this.children = []; } function Mesh( geometry, material ) { Object3D.call( this ); }

4. bind( ):
这是 ECMAScript5 新增的方法, 它返回一个新的函数, 所以它不会直接执行函数, 需要最后加上 ( ) 才会输出结果. function f(y){ return this.x + y; } var obj = {x: 1}; var g = f.bind(obj); console.log( g(2) ); // 3