在JavaScript里使用typeof判断数据类型,只能区分基本类型,即:number、string、undefined、boolean、object。对于null、array、function、object来说,使用typeof都会统一返回object字符串。
对于这个问题,我们可以使用 Object.prototype.toString.call() 的方法解决。
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call(“abc”);// "[object String]"
Object.prototype.toString.call(123);// "[object Number]"
Object.prototype.toString.call(true);// "[object Boolean]"
1. call()
语法:
fun.call(thisArg[, arg1[, arg2[, ...]]])
thisArg:fun函数运行时指定的this值,可能的值为:
- 不传,或者传null,undefined, this指向window对象
- 传递另一个函数的函数名fun2,this指向函数fun2的引用
- 值为原始值(数字,字符串,布尔值),this会指向该原始值的自动包装对象,如 String、Number、Boolean
- 传递一个对象,函数中的this指向这个对象
call()、 apply()、 bind() 的区别:
call()、 apply() 基本一样,只是 apply 参数接受一个数组,而 call 接受若干个参数。bind()函数实际上是新建一个函数,不会立即执行,需要调用才能执行。
创建一个对象的时候,new 都做了什么事情:
var a = new myFunction("Li","Cherry");
new myFunction{
var obj = {};
obj.__proto__ = myFunction.prototype;
var result = myFunction.call(obj,"Li","Cherry");
return typeof result === 'obj'? result : obj;
}
从上述过程可以看出来:
- 创建一个空对象 obj;
- 将新创建的空对象的隐式原型指向其构造函数的显示原型。
- 使用 call 改变 this 的指向
- 如果无返回值或者返回一个非对象值,则将 obj 返回作为新对象;如果返回值是一个新对象的话那么直接直接返回该对象。
----------------------------------------- call apply bind 常用的应用场景 -------------------------------
call apply bind 常用的应用场景
(一) 求数组中的最大和最小值
var arr = [34,5,3,6,54,6,-67,5,7,6,-8,687];
Math.max.apply(Math, arr);
Math.max.call(Math, 34,5,3,6,54,6,-67,5,7,6,-8,687);
Math.min.apply(Math, arr);
Math.min.call(Math, 34,5,3,6,54,6,-67,5,7,6,-8,687);
(二) 将伪数组转化为数组
什么是伪数组?
1. js 的伪数组是一个包含 length 属性的 json 对象,length 是必备的。
2. 它是按照索引的方式存储数据的。
3. 它不具备数组拥有的方法,只能通过 call 或者 apply 转化为数组后才能使用。
例如:
var obj = {0:'a',1:'b',length:2}; // 伪数组
var arr = Array.prototype.slice.call(obj); // 转化为数组
console.log(arr); // 返回["a","b"]
如何将伪数组转化伪数组?
- [].slice.call()这种形式实现同样的效果
- Array.prototype.slice.call()
为什么可以将伪数组转化伪数组,下面是 Array 对象的 slice 方法的实现过程?
function slice(obj) {
var arr =[];
var len = obj.length; // length 正好对应伪数组中的length属性
for(var i = 0;i < len;i++){
arr.push[i] = obj[i]; // i 正好对应伪数组中的索引值
}
return arr;
}
这个过程显示了一个伪数组对象 obj 经过一系列操作变成 arr 返回,因此可以看出,对于一个伪数组对象,length 是必须的,且伪数组的键必须是 0,1,2...length - 1 这种方式排列的。
常见伪数组有:
- 函数的参数 arguments 对象。
- getElementsByTagName 等方法。
- document.childNodes 方法。
(三) 数组的 push 方法
var arr1 = [1,2,3];
var arr2 = [4,5,6];
[].push.apply(arr1, arr2);
// arr1 [1, 2, 3, 4, 5, 6]
(四) 判断数据类型
对于对象型的数据类型,我们可以借助call来得知他的具体类型,例如数组
function isArray(obj){
return Object.prototype.toString.call(obj) == '[object Array]';
}
isArray([]) // true
isArray('qianlong') // false
(五) 利用call和apply做继承
var Person = function (name, age) {
this.name = name;
this.age = age;
};
var Girl = function (name) {
Person.call(this, name);
};
var Boy = function (name, age) {
Person.apply(this, arguments);
}
var g1 = new Girl ('qing');
var b1 = new Boy('qianlong', 100);
网友评论