JavaScript from an array of indexof () the property mechanism of the object in depth _javascript tips

Source: Internet
Author: User
Tags arrays

In JavaScript, arrays can be created using the array constructor, or created quickly using [], which is also the preferred method. An array is a prototype that inherits from object, and he has no special return value for TypeOf, and he only returns ' object '.

JS, you can say that everything is objects (object), an array is also an object (array).

Many objects have many convenient methods such as array push,concat,slice and so on, but if some objects, it does not implement these methods, we still want to use these features. So what should we do?

1, many methods provide a very efficient implementation, we can imitate their implementation.

For example, the browser below IE8 does not support the IndexOf method of array, in order to allow the array to support indexof, we can write a method to implement the IndexOf method:

(with IE browser debugging press F12, you can choose Browser version to IE5.) )

var arr = [,,,];
if (Array.prototype.indexOf) {
alert ("Your browser supports the IndexOf method.) ");
} else {
alert ("Your browser does not support the IndexOf method.") ");
}
if (! Array.prototype.indexOf) {
Array.prototype.indexOf = function (item) {for
(var i =; i < this.length; i++) {
   if (This[i]==item) {return
i;
}
}
return-;
}
}
Alert (Arr.indexof ());

Of course, this method is very rubbish. In this specific implementation I will not shortcoming, to provide a copy of Baidu version:

If you are interested, you can see how the V8 engine is implemented: Https://github.com/v8/v8/blob/master/src/js/array.js

if (! Array.prototype.indexOf)
{
Array.prototype.indexOf = function (ELT/*, from*/)
{
var len = this.length >>>;
var from = number (arguments[]) | | ;
From = (from <)
? Math.ceil (from)
: Math.floor (from);
if (from <) from
+ = Len;
for (; from < Len; from++)
{
if (
this[from) = = ELT) return from
;
return
-;
};

2, Inherit--call and apply method

If we each have an object, then each object must write their own implementation is not very troublesome?

In a high-level language, we can use inheritance to solve problems, such as the following Java code:

public class Mylist<e> extends arraylist<e>
{public
void Myadd (e) {
super.add (e);
System.out.println ("ADD:" +e);
}

But JS does not have the concept of inheritance Ah, we can use call and apply to solve such problems.

The above code can be rewritten as:

var myObject = function () {
}
MyObject.prototype.add = function () {
Array.prototype.push.call (this, arguments);
Output arguments for
(var i=;i<arguments.length;i++) {
console.log ("ADD:" +arguments[i]);
}
var obj = new MyObject ();

As you can see here: Although the Myadd method is implemented using advanced language inheritance, the Myadd method can now only pass one argument, and if you want to pass multiple arguments, you need to write a public void Myadd (e[) E) method, or even a public void Myadd ( List<e> E) method. And JS with a method can be done, with the arguments object to represent all the input parameters, this is a high-level language is difficult to do.

(PS, in fact, in Java can write public void Myadd (E. E), this is an indefinite parameter, the usage of public void Myadd (e[] e) is the same)

The call and apply methods are used to change the point of this pointer in the function, call has only two parameters, and apply is usually known after the number of parameters to use, the following examples illustrate:

var Obj = function (name) {
this.name = name;
}
Obj.prototype.getName = function () {return
this.name;
}
var obj1 =new Obj ("Zou");
var obj2 = {name: ' Andy '};
var name = Obj1.getName.call (OBJ2);

Reference is:

Apply (Object,arg1,arg2,....)
Call (Object,[arg1,arg2,....])

Call can only be followed by an "array", including all the parameters. and apply is a grammatical sugar, if you know the number of parameters, apply will be very convenient.

The object above can also be null or undefined, so that the object is Global Object (window), for example, or the following example:

var name = ' Goo ';
Alert (Obj1.getName.call (null)); 
(in strict mode, an exception is thrown because the global object is null: uncaught typeerror:cannot Read Property ' name ' of NULL)

3, Object.defineproperty

(Note: Do not use this type of attribute below IE8)

Microsoft: Add attributes to an object, or modify the attributes of an existing property.

Getter, Setter,

In fact JS for object properties also have getter and setter function, but the individual feel JS in the getter and setter more like C # some.

For example, the following code defines a getter/setter:

function MyObj () {
}
object.defineproperty (myobj.prototype, ' length ', {
get:function () {
return This.length_; This cannot be length.
},
set:function (value) {return
This.length_=value
}

The annotation cannot be a length, otherwise it will be infinitely recursive.

You can also remove the set and make the length variable read-only.

Object.defineproperty (myobj.prototype, ' length ', {
get:function () {return
this.length_;//This cannot be length.
}, 
/*set:function (value) {return
This.length_=value
} */
});

This code throws an exception: uncaught typeerror:cannot set length of #<myobj> which has only a getter.

To make the properties of an object read-only, you can also use Writable:false,

Object.defineproperty (myobj.prototype, ' length ', {
writable:false
});

Writable:false cannot coexist with get set, or it throws a type Error.

Configurable: It can be deleted with the DELETE statement, but the configurable property appears to be valid in strict mode, and the code can still execute in a strict mode: (Strict mode error)

Object.defineproperty (myobj.prototype, ' length ', {
configurable:false
});
var obj = new MyObj ();

Value: Specifies the fixed value of the object. Value:10, which indicates that the initial value of this object is 10.

In the non strict mode, such code does not complain, strict mode will be an error:

Object.defineproperty (myobj.prototype, ' length ', {
writable:false,
value: '} '
);
var obj = new MyObj ();

You can use Getownpropertydescriptor to get and modify these values, for example, now my Length property is read-only.

Run this code, and the result is an error:

Object.defineproperty (myobj.prototype, ' length ', {
value:,
writable:false,
});
var descriptor = Object.getownpropertydescriptor (Myobj.prototype, 
"Length");
Descriptor.writable = true;
Object.defineproperty (myobj.prototype, ' length ', descriptor); 
Uncaught Typeerror:cannot Redefine Property:length

This is because the default value of configurable is false, and after the DefineProperty is invoked, configurable has a false attribute, which cannot be reversed. You can't change it later.

So you have to use Configurable:true, the object property is modifiable, and the complete code is as follows:

Object.defineproperty (myobj.prototype, ' length ', {
value:,
writable:false,
configurable:true
});
var descriptor = Object.getownpropertydescriptor (Myobj.prototype, 
"Length");
Descriptor.writable = true;
Object.defineproperty (myobj.prototype, ' length ', descriptor);
Myobj.prototype.length =;
var obj = new MyObj ();

Can add a sentence descriptor.configurable = false;

Represents this property I changed it, and you can't change it anymore.

This feature is also useful in many cases, such as the push pop for array arrays, which requires that the length of the object be variable if you use call and apply. If the length property of an object is read-only, an exception is thrown when calling call, apply.

Just like the Domtokenlist object, its length cannot be changed. I got a DOM object domtokenlist,

But its configurable is true, and we can modify the length attribute to change it:

See, this configurable is true, and the setter is undefined, let's write a set method for it, can we?

var descriptor = Object.getownpropertydescriptor (domtokenlist.prototype, ' length ');
Descriptor.set = function (value) {
this.length = value;
}

And then run,

Another exception was thrown, uncaught rangeerror:maximum call stack size exceeded (...)

This is because when we do set this.length, it is infinitely recursive in the set method that we write.

Therefore, we need to use Delete to eliminate the effect of the length property, namely:

var descriptor = Object.getownpropertydescriptor (domtokenlist.prototype, ' length ');
Descriptor.set = function (value) {
delete DOMTokenList.prototype.length;
This.length = value;
}

In this way, Domtokenlist also support the Push,pop and so on operation.

Array.prototype.push.call (document.body.classList, ' abc ')

And then wrap it again.

DOMTokenList.prototype.push = function () {
Array.prototype.push.call (document.body.classList), Array.prototype.slice.call (arguments));

The Array.prototype.slice.call (arguments) method is used to convert arguments objects into arrays.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.