Object creation review
- Object direct quantity
- Using the new operator
- Object.create() method
reference resources: Section 3: data type - Object object
When we create objects, we usually create a single object. If we need to create multiple objects, there may be a lot of duplicate code.
this point resolution
① In the function: this represents the global scope. If it is in the browser, it represents window
var x=5; function fun(){ let x=1; console.log(this.x,this); } fun();//5. Window and this point to the global scope
② Methods and properties of objects: pointing to objects
var x=5; var obj={ x:1, f:function(){console.log(this.x)} } obj.f();//1. this points to obj
③ In the constructor, this points to the new object created
function fun(x,y){ this.x=x; this.y=y; console.log(this.x,this.y,this); } const newF1=new fun(1,5);//Result: 1 5 fun {x: 1, y: 5}
④ To forcibly point to an object, you need to use the functions apply() and call()
The difference between call() and apply():
The call() method accepts parameters separately.
The apply() method accepts parameters in the form of an array
//Do not receive parameters var person = { firstName:'leo', lastName:'dd', fullName: function() { return 'Hello ' + this.firstName + " " + this.lastName + '!' } } var person1 = { firstName:"John", lastName: "Doe" } person.fullName();//"Hello leo dd!" person.fullName.apply(person1)//"Hello John Doe!" person.fullName.call(person1);//"Hello John Doe!" //Receive parameters var person = { firstName:'leo', lastName:'dd', fullName: function(city, country) { return this.firstName + " " + this.lastName + "," + city + "," + country; } } var person1 = { firstName:"John", lastName: "Doe" } person.fullName('USA','count');//"leo dd,USA,count", the default point of this is the person object person.fullName.apply(person1,['USA','count']);//"John Doe,USA,count", modify this point to the person object person.fullName.call(person1,'USA','count');//"John Doe,USA,count", modify this point to the person object
reference resources: Special objects - function details
reference resources: this principle of JavaScript -- Ruan Yifeng
Patterns used in creating objects and their advantages and disadvantages
1. Factory mode: wrap the process of creating objects with functions, and run the functions every time you create objects. This function is equivalent to the factory for creating objects.
function createPerson(name,age,job){ var obj={}; obj.name = name; obj.age=age; obj.job=job; return obj; } var zs=createPerson('Zhang San',18,'student'); var ls=createPerson('Li Si',27,'designer'); zs.constructor;//ƒ object() {[native code]} is an object that cannot be determined whether it is created by createPerson
Disadvantages: the type of object is not recognized
2. Constructor mode
Constructors are generally conventionally capitalized with the first letter.
Constructor attribute: it is a pointer to the constructor of the current object. You can determine whether two objects are created by the same constructor.
The procedure performed by the new operator:
- Create an object
- Assign the constructor scope to the new object
- Implement all the code in the function
- Return object
function Person(name,age,job){ this.name = name; this.age = age; this.job=job; this.cName=function(){ alert(this.cName) } } var per1=new Person('Zhang San',18,'student'); var per2=new Person('Li Si'); per1.constructor == Person;//true determines whether per1 is constructed from Person constructor per2.constructor == per1.constructor;//true points to the same constructor per2.constructor === per1.constructor;//true
The typeof operator can be used to detect the basic data type. All objects returned by the typeof query Object are objects, while the instanceof operator can be used to detect the constructor
function Person(name,age,job){ this.name = name; this.age = age; this.job=job; this.cname=function(){ alert(this.cname); } } var per1=new Person('Zhang San',18,'student'); var obj={name:'test'}; typeof per1;//'object' per1 instanceof Object;//true per1 instanceof Person; //true obj instanceof Person; //false obj instanceof(Person);//false //The function constructor created in factory mode is Object, and the constructor returns the name of the constructor zs.constructor;//ƒ Object() { [native code] } per1.constructor;//ƒ Person(name,age,job){ this.name = name; this.age = age; this.job=job;}
The constructor is no different from ordinary functions, except that it is created using the new operator. this points to a new object.
Constructor disadvantages:
Every instantiated object has a CNAME method. Although the functions are the same, Per1 cname == per2. cname; false, so many methods with the same functions will be created, occupying memory. The solution is shown in the following code:
//First create a public method, and then assign this public method to an attribute of the constructor; var cc=function(){ alert(this.cname); } function Person(name,age,job){ this.name = name; this.age = age; this.job=job; this.cname=cc; } var per1=new Person('Zhang San',18,'student'); var per2=new Person('Li Si',25,'Design'); per2.cname == per1.cname;//true
The problem of this method is that the public method occupies memory and cannot avoid the problem of duplicate names, so another pattern, prototype pattern, appears
3. Prototype mode
In JavaScript, prototype object is an important mechanism to realize object-oriented.
Prototype object: any function has a prototype attribute. Prototype corresponds to an object, which is called a prototype object. (each object has a constructor attribute)
function person(){} person.prototype;//{constructor: ƒ} //Add attributes to prototype objects person.prototype.name='test'; person.prototype.age=18; person.prototype;//{age: 18, name: 'test', constructor: ƒ} //Instantiating an object will get all the attributes and methods on the prototype object. When multiple objects have the same method and attribute, a new attribute and method will be generated every time they are created, which takes up memory var per1=new person(); var per2=new person(); per1.name;//'test ' per1.name==per2.name;//true
Why is perl.1 on the prototype pattern name==per2. name;
Inside each object, there is a pointer to the prototype object of its constructor. Under normal circumstances, this pointer is inaccessible, but now most browsers can use it__ proto__ Access to__ proto__ Prototype object pointing to person.
per1.__proto__;//Get the prototype object {age: 18, name: 'test', constructor: ƒ} of the constructor of per1
Find properties:
When using Per1 name; When accessing the name attribute, you will first find out whether there is this attribute on person. If there is, you will return it. If not, you will find the method on the prototype object along the prototype attribute. If there is, you will return it. If not, you will return undefined; This is prototype chain lookup
per1;//person {} person.prototype;//{age: 18, name: 'test', constructor: ƒ} per1.job='work'; per1;//person {job: 'work'}
Create / set properties:
When creating an attribute, the prototype chain of prototype will not be searched, and the existence of this attribute on the object will be judged. If not, it will be created directly. A problem (the same name masking problem) appears.
Solution: first, try to avoid the same name; If you have the same name, you can use delete to delete the attribute with the same name.
per1.job='work'; per1;//person {job: 'work'} per1.name='Modify name'; per1;//person {job: 'work', name: 'modify name'} per1.name;//Modifying the name will directly call the then attribute in person without looking up the prototype object of the prototype attribute delete per1.name; per1.name; //'test '
The properties and methods of the object can be deleted using delete.
Why all objects can use the toString and valueOf methods: This is because these two methods exist on the prototype pair. Therefore, if you can't find the object, you can also find these two methods when it's as good as the root node prototype object.
In addition to the toString and valueOf methods, there is isPrototypeOf(),
isPrototypeOf(): returns a Boolean value indicating whether the object called by the method is in the prototype chain of the specified object. If it exists, it returns true; otherwise, it returns false
hasOwnProperty(): returns a Boolean value indicating whether an object itself contains the specified property. This method will not find the inherited property on the prototype chain
//isPrototypeOf() is used to test whether one object exists on the prototype chain of another object var f = function () {} //Define function f.prototype = { //Prototype object of function a : 1, b : function () { return 2; } } var b = new f(); //Instantiate object f.prototype.isPrototypeOf(b);//True f.prototype is the prototype object of object b //Determine whether the age and a attributes belong to the b object b.age=20; b.hasOwnProperty('a');//False a is an attribute on the prototype b.hasOwnProperty('age');//Property with true age of b
reference resources: Object instance method
The for in loop can obtain all enumerable attributes, not only the attributes of the current object, but also the attributes on the prototype chain
Get all attributes, free attributes and prototype attributes
Object.prototype.score = '97'; var people = { name:'Xiao Hong', age : 15, } //Get all properties for(let key in people ){ console.log(key+':'+people[key]); } //Method 1 for obtaining free attribute for(let key in people ){ if(people.hasOwnProperty(key)){ console.log(key+':'+people[key]); } } //Method 2 for obtaining free attribute Object.keys(people);//['name','age'] //Get the prototype attribute. Remove all the free attributes to get the prototype attribute var arr=[];//All properties for(let key in people ){ arr.push(key); } var narr=Object.keys(Person); //Free attribute var proArr=[]; //Prototype properties for(let i=0;i<arr.length;i++){ if(narr.indexOf(arr[i])<0){ proArr.push(arr[i]); } } proArr; //['score']
***