prototype related methods, jquery type judgment source code analysis.

Posted by jbardin on Mon, 27 May 2019 23:49:27 +0200

Preface

Introduce the concept of prototype, related attributes, and the implementation of jquery to judge the pure object, and carelessly come in to search for the attributes you want directly ctrl+f.

  1. What is prototype

  2. isPrototypeOf() || Object.getPrototypeOf()

  3. hasOwnProperty() || in

  4. jQuery.isPlainObject() Source Code Interpretation

What is prototype

Prototype (prototype, prototype, prototype) says that a prototype of a new mobile phone can use this word.
Each function has a prototype property by default, which points to the prototype object of the function. That is to say, the prototype of a function is an object. First, print the prototype attribute of a function to see what it looks like.

function Zoom(){};
var proto = Zoom.prototype;
console.log(proto);

Seeing is believing. This is the prototype object of Zoom function. There is also a constructor attribute. We haven't modified the prototype prototype object, but we have a constructor attribute. By default, the prototype object of the function gets a constructor attribute.
Constructor is interpreted as constructor in English. The attribute value of the constructor in the graph is a Zoom function. It is easy to remember and understand that the prototype of function is generated by function. What constructs the prototype is the function itself. That is:

Zoom.prototype.constructor = Zoom;
//Language description is: the constructor attribute of the prototype object of zoom function points to the function itself.

When we get an instance of a constructor through the new operator (that is, an object is generated). Let's first look at an object like this:

function Zoom(){
  this.bird = function(){
    console.log('bird');
  }
};
//A method is extended on the prototype of function.
Zoom.prototype.cat = function(){
  console.log("cat");
}
var zoom = new Zoom();
console.log(zoom);

You can see that under the instantiated zoom object there is a _proto_ attribute, which points to the prototype object of the constructor Zoom. The point is that _proto_ connects the instance object with the constructor prototype object, not the instance object and the constructor.

isPrototypeOf() || getPrototypeOf()

function Zoom(){
  this.bird = function(){
    console.log('bird');
  }
};
//A method is extended on the prototype of function.
Zoom.prototype.cat = function(){
  console.log("cat");
}
Zoom.prototype.fish= function(){
  console.log("fish");
}
var zoom1 = new Zoom();
var zoom2 = new Zoom();
zoom1.cat ();//cat
zoom2.fish();//fish
console.log(zoom1);
console.log(zoom2);

According to the previous section, zoom1 and zoom2 instance objects have an attribute _proto_ pointing to the prototype object of the constructor. In other words, there is no direct connection between the instance object and the constructor.
However, we find that neither of these two instances contains methods, but can use methods a and b, which is achieved by the process of finding object attributes.
When we call the attribute value of an object, we first search from the instance object itself. If we find it, we return the attribute value. If we do not find it, we search on the prototype object. This is why the properties or methods of prototype objects can be shared.
How do you know if there is a way to construct a function's prototype object (Zoom) in an object, such as a prototype chain of two instances? This is isPrototype Of (). Used to determine whether an object exists in the prototype chain of another object.

console.log(Zoom.prototype.isPrototypeOf(zoom1));//true

Although prototypes can be shared, they cannot be modified through instance objects:

zom1.cat = function (){
  console.log('zom1 Output cat');
}
zom1.cat ();//z1 output cat
zom2.cat ();//cat of prototype output

This is actually very easy to understand, because object attribute lookup is from the instance to the prototype, so if the method written on the instance is the same name as the method on the prototype, it will shield the method on the prototype, which can be simply understood as the principle of proximity.

hasOwnProperty() || in

Since the same method can appear in an instance or in a prototype, how can we determine whether or not it is in an instance?
The hasOwnProperty() method returns a Boolean value indicating whether the object has a specified property as its own (non-inheritance) property.
If we judge whether there is a attribute in the zoom1 object itself, we can:

zoom1.hasOwnProperty(bird); // true
zoom1.hasOwnProperty(fish); // false

Because bird is the property of zoom1 itself, it returns true, while fish is the property of zoom1 prototype, so it returns false.
Another in method to be introduced, which is more extensive than hasOwnProperty judgment, returns true if there are attributes to be detected, either prototypically or in an instance.

'bird' in zoom1; // true
'fish' in zoom1; // false

That can be understood as excluding hasOwnProperty from the judgment scope of in method, leaving the possibility that attributes only appear in the prototype.
Conversion to simple logic is that if in is true, it may be in the instance or in the prototype, and if hasOwnProperty method is false, it is certainly not in the instance. So if in is true and hasOwn Property is false, it must be in the prototype:

function hasProtoTypeProto(attr,obj){
   return !obj.hasOwnProperty(attr) && (attr in obj)
}
hasProtoTypeProto('fish',zoom1) //true
hasProtoTypeProto('bird',zoom1) //false

isPlainObject()

jquery provides an external method that can be used directly to determine whether an object is a pure object, that is, an object literal quantity, rather than an instance of a constructor. It covers most of the prototype-related methods. Let's first see how to use it.

var log = console.log.bind(console);
log(jQuery.isPlainObject({x:0}));//true
log(jQuery.isPlainObject(new Object({})))//true
log(jQuery.isPlainObject([0]))//false
function Zoom(){
  this.fish = function(){
    return "Im a fish";
  }
}
var zoom = new Zoom();
log(jQuery.isPlainObject(zoom))//false

You can see that only pure objects return true, typeof type detects that arrays are objects, or instances of constructors return false. Let's take a look at how this approach is implemented in jQuery version 3.1. See the code for the analysis process:

//Input of objects to be judged
function isPlainObject(obj) {
//There is no specific meaning but to preserve the results of other executions.
var proto, Ctor;
if (!obj || toString.call(obj) !== "[object Object]") {
  // ToString has been defined as Object.prototype.toString in the previous code, code equivalent to Object.prototype.toString. call (obj)!=="[object object object object]"
  //Calling Object's native toString() method on any value returns a string in [object Native Constructor Name].
  //[[Class]] is an internal property that is owned by all objects (native and host objects), in which the name of the constructor (Native Constructor Name) in the above string is specified.
  // Similar [object Array] [object Function] [object RegExp]
  //However, this judgment cannot exclude an instance object, because the [[Class]] attribute saves the type of object by default, so it also returns Object.
  //So except for other types of objects, false is returned.
  return false;
}
proto = getProto(obj);
// GetProto has been previously defined as the prototype of getProto = Object.getPrototypeOf return object constructor
// Objects with no prototype (e.g., `Object.create( null )`) are plain
// The previous line is a sitting comment, that is, through the Object. create (null) method, you can create an object null without a prototype
// So if proto is false, it means that the object has no prototype, it will only be null, and null is a pure object, so it returns true.
if (!proto) {
  return true;
}

Ctor = hasOwn.call(proto, "constructor") && proto.constructor;
// Objects with prototype are plain iff they were constructed by a global Object function
// HasOwn was previously defined as hasOwn = {}. hasOwn Property 
// HasOwn. call (proto, "constructor") passes into the prototype of the Object constructor to determine whether there are constructor attributes on the prototype (not at other places in the prototype chain), because the constructor attributes only appear on the prototype of the Object function, and the constructor attributes of other function prototypes are inherited from the prototype of the Object.
// So the constructor attribute representation is obtained through the Object object, but it can not be determined as an instance of Object or literally. Finally, the proto.constructor is saved as the constructor of the incoming object.


return typeof Ctor === "function" && fnToString.call(Ctor) === ObjectFunctionString;
// fnToString is defined as hasOwn.toString, which is {}. hasOwnProperty.toString.call(Ctor);
// Object FunctionString is defined as fnToString. call (Object) which is {}. hasOwnProperty.toString.call(Object);
// So typeof Ctor ='fuction'is a function that needs to be judged that the prototype of the object is a function type. The purpose of {}. hasOwnProperty is to get a function, and the toString method of a function will display the function in the form of a string.
// If two strings are equal, two functions are equal. It means that the constructor of the incoming object is Object, so it is a pure object.

}

So far, this is all the content of the full text. If you have any questions, leave a message and reply.

Topics: Javascript Attribute JQuery Mobile