首页天道酬勤call语句的作用,call的其他形式

call语句的作用,call的其他形式

admin 08-27 10:08 312次浏览

call()定义:使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。 

简言之:设置函数体内this对象的值

var a = 11;var b = 12;function add(c, d){ console.log(this.a + this.b + c + d); } var o = {a:1, b:3}; add(5, 7); // 35add.call(this, 5, 7); // 35add.call(window, 5, 7); // 35add.call(o, 10, 20); // 34 function test(a,b,c,d) { var arg = Array.prototype.slice.call(arguments,1); console.log(arg);} test("a","b","c","d"); // b,c,d

注意:

(1)、MDN上关于slice()处理类数组的解释: slice 方法可以用来将一个类数组(Array-like)对象/集合转换成一个新数组。你只需将该方法绑定到这个对象上。 一个函数中的arguments就是一个类数组对象的例子;

(2)、slice()若不传参数则默认从0开始提取数组元素,返回新提取后的数组;

解释:

(1)、因为arguments并不是真正的数组对象,只是类数组,所以它并没有slice这个方法,而Array.prototype.slice.call(arguments, 1)可以理解成是让arguments转换成一个数组对象,让arguments具有slice()方法,要是直接写arguments.slice(1)会报错。其实这里相当于在test()函数内执行了arguments.slice(1),这种方法的使用又称为借用方法

(2)、除了使用 Array.prototype.slice.call(arguments),你也可以简单的使用 [].slice.call(arguments) 来代替;

(3)、还可以使用bind简化该过程(下面这段代码可忽略,和接下来要讲的代码是同一段):

var slice = Function.prototype.call.bind(Array.prototype.slice);function list() { return slice(arguments);}console.log(list(1, 2, 3)); // [1, 2, 3] var slice = Function.prototype.call.bind(Array.prototype.slice)function list() { return slice(arguments);}console.log(list(1, 2, 3)); // [1, 2, 3]var join = Function.prototype.call.bind(Array.prototype.join);console.log(join('abc', '|')); // 'a|b|c'

解释:

(1)、Function.prototype.call是一个引用,用来调用一个函数(slice())并且把它的“this”值设置为其内部提到的方法;

(2)、记住“bind”返回一个新的函数,这个函数总是会牢记它的“this”值,因此,.bind(Array.prototype.slice)会返回一个新的函数,它的“this”被永久地设置成了 Array.prototype.slice 函数;

(3)、通过结合以上两个,我们现在有了一个新的函数,它将会调用“call”函数并且“this”限定为了“slice”函数,简单地调用slice()便可以引用之前限定的方法。join()原理相同;

var toUpperCase = Function.prototype.call.bind(String.prototype.toUpperCase);console.log(String.prototype.toUpperCase.call(['lowercase', 'words', 'in', 'a', 'sentence']));// LOWERCASE,WORDS,IN,A,SENTENCEconsole.log(toUpperCase(['lowercase', 'words', 'in', 'a', 'sentence']).split(','));// ["LOWERCASE", "WORDS", "IN", "A", "SENTENCE"]

解释:

String.prototype.toUpperCase.call()会将任何非字符串形式的值转换成字符串, bmdbks把这个值的 this 设置成一个不是字符串的值;  

注意: 

接下来要讲的也是和call()有关,就是大家公认的判断所有js类型的通用方法Object.prototype.toString.call()

var obj = { a: 2}console.log(Object.prototype.toString.call(obj) === "[object Object]"); // true

相信 Object.prototype.toString.call()方法对于大家来说并不陌生,下面来解释下为什么要这样判断数据类型:

console.log(Object.prototype.toString.call("gdddc")); // [object String]console.log(Object.prototype.toString.call(12)); // [object Number]console.log(Object.prototype.toString.call(true)); // [object Boolean]console.log(Object.prototype.toString.call(undefined)); // [object Undefined]console.log(Object.prototype.toString.call(null)); // [object Null]console.log(Object.prototype.toString.call({name: "gdddc"})); // [object Object]console.log(Object.prototype.toString.call(function(){})); // [object Function]console.log(Object.prototype.toString.call([])); // [object Array]console.log(Object.prototype.toString.call(new Date)); // [object Date]console.log(Object.prototype.toString.call(/\d/)); // [object RegExp]function Person(){};console.log(Object.prototype.toString.call(new Person)); // [object Object]

Object.prototype.toString()方法的解释说:toString() 方法返回一个表示该对象的字符串;

为什么我们不直接调用各类型自己的obj.toString()方法,如下:

console.log("gdddc".toString()); // gdddcconsole.log((1).toString()); // 1console.log([1,2].toString()); // 1,2console.log(new Date().toString()); // Tue Oct 22 2019 15:55:35 GMT+0800 (中国标准时间)console.log(function(){}.toString()); // function (){}console.log(null.toString()); // TypeErrorconsole.log(undefined.toString()); // TypeErrorconsole.log({a: 2}.toString()); // [object Object]

 由于undefined和null不是对象,所以它们toString()和valueOf()两个方法都没有,直接调用会报错;

可以对比看出:obj.toString()的结果和Object.prototype.toString.call()的结果不一样!

原因解释:

(1)、toString为Object的原型对象上的方法,而Array 、Function等类型作为Object的实例,都重写了toString方法,在自己的原型对象上;

(2)、不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法((Function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串.....),而不会去调用Object原型对象上的toString方法(返回对象的具体类型);

(3)、obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;

(4)、因此,在想要得到对象的具体类型时,应该调用Object原型对象上的toString方法;

 接下来我们看一段代码,我们将数组原型对象上的toString方法删除,再执行obj.toString(),如下:

var arr=[1,2,3];// hasOwnProperty判断对象是否拥有某个属性,不检查原型链console.log(Array.prototype.hasOwnProperty("toString"));// trueconsole.log(arr.toString()); // 1,2,3delete Array.prototype.toString; // delete操作符可以删除自有属性,不能删除继承属性console.log(Array.prototype.hasOwnProperty("toString")); // falseconsole.log(arr.toString()); // "[object Array]"

 解释:

(1)、删除了Array的toString()方法后,再调用arr.toString(),此时由于实例本身在对应的原型对象上没找到toString(),会沿着原型链找到Object.prototype.toString(),进而调用它,即arr.toString(),所以返回了和Object.prototype.toString.call(arr)一样的结果;

(2)、使用Object.prototype.toString.call(arr)说白了也是用到了‘借用方法’思想。

Spring Cloud原理及核心组件是什么Rust中FFI编程知识点有哪些Maven版本:使用git时准备使用NoClassDefFoundError前端node Session和JWT鉴权登录怎么实现计算一个字符串中有多少回文node.js环境变量指的是什么UsinguseState()withanobjectasstate
call指令的用法及功能,call指令详解 mysql存储过程存在哪个表里,mysql数据库备份的步骤
相关内容