In this series, underscore gets a feel for the idea of functional programming by reading the source code and doing the work instead of going through lengthy text tutorials. Underscore, with a minimum of 1,500 lines of detail, helps write code that is poorly coupled and confortable with functional programming ideas. In addition, we can learn the difference between the efficiency of Call and apply to optimize the code performance.

Welcome everyone star or Watch this series, your attention is the biggest motivation of the author, let us continue to make progress together. This series of warehouses: github.com/zhangxiang9…

Typeof

We all use Typeof as a command for determining data types, which in normal scenarios is sufficient to meet the requirements of determining data types:

var obj = {
   name: 'zhangxiang'
};

function foo() {
    console.log('this is a function');
}

var arr = [1,2,3];

console.log(typeof 1);  // number
console.log(typeof '1');  //string
console.log(typeof true);  //boolean
console.log(typeof null); //object
console.log(typeof undefined); //undefined
console.log(typeof obj); //object
console.log(typeof foo);  //function
console.log(typeof arr);   //objectCopy the code

As you can see, the Typeof command can determine all the basic data types in javascript (Null, Undefined, Boolean, String, Number), even though Null uses typeOF to return object strings, However, in complex scenarios such as object and NULL, array and object, function and object, etc., typeof can be difficult to use. So in general, Typeof is used in simpler scenarios, where you can almost determine what kind of data the data is and then differentiate it a little bit. Here’s a simple example to illustrate the situation:

function unique(array){
  var hash = {};
  var result = [], key;
  array.forEach(function(item, index){
    key = item;
    if(typeof item === 'string') {
      key = '_' + item;
    }
    if(!hash[key]) {
      result.push(item);
    } else {
      hash[key] = true; }});return result;
}Copy the code

instanceof

Instanceof is useful for determining custom class instance objects, not native datatypes, for example:

Var a = [1,2,3]; </script>Copy the code
//main.html
<iframe src="a.html"></iframe>

<script>
  var frame = window.frame[0];
  var a = frame.a;
  console.log(a instanceof Array);  // false
  console.log(a.contructor === Array);  //false
  console.log(a instanceof frame.Array); // true
</script>Copy the code

What causes the above results? In fact, iframes do not share prototype chains because they have separate execution environments, so array A in Frame A is not an instance object of this execution environment. Sniffing through properties is also unreliable, as is using specific array (or other data type) methods or attributes via Contructor sort, slice, etc., in case the object also has a Sort, slice attribute. So most of method is to use the Object. The prototype. The toString method.

Object.prototype.toString

Use the Object. The prototype. The toString method, can obtain the accurate type of variable.

function foo() {}; Object.prototype.toString.call(1);'[object Number]'
Object.prototype.toString.call('1'); '[object String]'
Object.prototype.toString.call(NaN); '[object Number]'
Object.prototype.toString.call(foo);  '[object Function]'Object. The prototype. ToString. Call ([1, 2, 3]);'[object Array]'
Object.prototype.toString.call(undefined); '[object Undefined]'
Object.prototype.toString.call(null); '[object Null]'
Object.prototype.toString.call(true); '[object Boolean]'.Copy the code

Object. The prototype. ToString works when the call value is within [[Class]] attribute value, then joining together into a ‘[Object]’ + [[Class]] + ‘ ‘this string and returns. We then use the Call method to get the data type of any value.

Useful data type judge function

isArray polyfill

Underscore isArray is a built-in data type determination function for array types, but there are compatibility issues.

isArray = Array.isArray || function(array){
  return Object.prototype.toString.call(array) === '[object Array]';
}Copy the code

isNaN polyfill

Determining whether a number is NaN can’t be determined simply by using ===, because NaN is not equal to any number, including itself, so:

isNaN: function(value){
  return isNumber(value) && isNaN(value);
}Copy the code

IsNumber here is to use the above Object. The prototype. The toString for judgment, then use the isNaN value to judge, as to why you need to need to distinguish the Number before judging isNaN type, This is because the NaN is itself a digital type (Object. The prototype. ToString), in the isNaN ES6 only values for numeric types using NaN will return true, this is in order to simulate the ES6 isNaN.

Check if it is a DOM element

In a real project, we might need to check whether it is a DOM element object, and use the DOM object’s specific nodeType property to do this:

isElement: function(obj){
  return!!!!! (obj && obj.nodeType === 1); }Copy the code

Check whether it is an object

isObject: function(obj){
  var type = typeof obj;
  return type= = ='function' || typeof === 'object'&& obj ! == null; }Copy the code

An object is a set of key-values, or a function that is not null.

Check whether the Arguments object is polyfill

An Object is the arguments Object can be judged by the Object. The prototype. The judging toString, but low version of the browser does not support, they return is [Object Object], so need to be compatible:

isArguments: function(obj){
  return Object.prototype.toString.call(obj) === '[object Arguments]'|| (obj ! = null && Object.hasOwnProperty.call(obj,'callee'));
}Copy the code

The principle of compatibility is to use the object’s hasOwnProperty method to determine whether the object has a Callee property and thus whether it is a Arguments object.

If you feel you have gained something, please go to Github and give the author a star to show your support. Thank you. This series of warehouses: github.com/zhangxiang9…