Home >Web Front-end >JS Tutorial >Detailed introduction to creating objects in JavaScript

Detailed introduction to creating objects in JavaScript

零下一度
零下一度Original
2017-06-28 13:43:131017browse

This article mainly introduces the relevant information of JavaScript created objects to everyone in detail. It has certain reference value. Interested friends can refer to

JavaScript is useful for each Each created object will have a prototype set to point to its prototype object.

When we use obj.xxx to access the properties of an object, the JavaScript engine first searches for the property on the current object. If it is not found, it searches on its prototype object. If it is not found yet, It goes all the way back to the Object.prototype object. Finally, if it is not found yet, it can only return undefined.
For example, create an Array object:

var arr = [1, 2, 3];

The prototype chain is:

arr ----> Array.prototype --- -> Object.prototype ----> null

Array.prototype defines indexOf(), shift() and other methods, so you can directly Call these methods.
When we create a function:

function foo() {
  return 0;
}

The function is also an object, and its prototype chain is:

foo ----> Function.prototype --- -> Object.prototype ----> null

Since Function.prototype defines methods such as apply(), all functions can call the apply() method.

It is easy to think that if the prototype chain is long, then accessing the properties of an object will become slower because it takes more time to look up, so be careful not to make the prototype chain too large. long.

Constructor

In addition to directly using { ... } to create an object , JavaScript can also use a constructor method to create objects. Its usage is to first define a constructor:

function Student(name) {
  this.name = name;
  this.hello = function () {
    alert('Hello, ' + this.name + '!');
  }
}

You may ask, hey, isn't this an ordinary function?

This is indeed an ordinary function, but in JavaScript, you can use the keyword new to call this function and return an object:

var xiaoming = new Student('小明');
xiaoming.name; // '小明'
xiaoming.hello(); // Hello, 小明!

Note that if you do not write new, This is a normal function, it returns undefined. However, if new is written, it becomes a constructor, the this it binds points to the newly created object, and returns this by default, that is, there is no need to write return this; at the end.

The prototype chain of the newly created xiaoming is:

xiaoming ----> Student.prototype ----> Object.prototype - ---> null

In other words, the prototype of xiaoming points to the prototype of function Student. If you create xiaohong and xiaojun, the prototypes of these objects are the same as xiaoming:
xiaoming ↘
xiaohong -→ Student.prototype ----> Object.prototype ---- > null
xiaojun ↗

The object created with new Student() also obtains a constructor attribute from the prototype, which points to the function Student itself:

xiaoming.constructor === Student.prototype.constructor; // true
Student.prototype.constructor === Student; // true

Object.getPrototypeOf(xiaoming) === Student.prototype; // true

xiaoming instanceof Student; // true

Are you dizzy? A diagram to represent these messy relationships is:

The red arrow is the prototype chain. Note that the object pointed by Student.prototype is the prototype object of xiaoming and xiaohong. This prototype object itself has an attribute constructor, which points to the Student function itself.
In addition, the function Student happens to have an attribute prototype that points to the prototype objects of xiaoming and xiaohong. However, xiaoming and xiaohong objects do not have the prototype attribute, but they can be viewed using the non-standard usage of proto.
Now we think that objects such as xiaoming and xiaohong "inherit" from Student.
But there is still a small problem. Pay attention to observation:

xiaoming.name; // '小明'
xiaohong.name; // '小红'
xiaoming.hello; // function: Student.hello()
xiaohong.hello; // function: Student.hello()
xiaoming.hello === xiaohong.hello; // false

xiaoming and xiaohong have different names. This is correct, otherwise we will not be able to distinguish who is who.
The respective hellos of xiaoming and xiaohong are one function, but they are two different functions, although the function name and code are the same!
If we create many objects through new Student(), the hello functions of these objects actually only need to share the same function, which can save a lot of memory.

To create objects that share a hello function, according to the property search principle of the object, we only need to move the hello function to the common prototype of xiaoming and xiaohong objects, which is Student. prototype:

Modify the code as follows:

function Student(name) {
  this.name = name;
}

Student.prototype.hello = function () {
  alert('Hello, ' + this.name + '!');
};

It’s that simple to use new to create prototype-based JavaScript objects!

What should I do if I forget to write new

如果一个函数被定义为用于创建对象的构造函数,但是调用时忘记了写new怎么办?
在strict模式下,this.name = name将报错,因为this绑定为undefined,在非strict模式下,this.name = name不报错,因为this绑定为window,于是无意间创建了全局变量name,并且返回undefined,这个结果更糟糕。
所以,调用构造函数千万不要忘记写new。为了区分普通函数和构造函数,按照约定,构造函数首字母应当大写,而普通函数首字母应当小写,这样,一些语法检查工具如jslint将可以帮你检测到漏写的new。
最后,我们还可以编写一个createStudent()函数,在内部封装所有的new操作。一个常用的编程模式像这样:


function Student(props) {
  this.name = props.name || '匿名'; // 默认值为'匿名'
  this.grade = props.grade || 1; // 默认值为1
}

Student.prototype.hello = function () {
  alert('Hello, ' + this.name + '!');
};

function createStudent(props) {
  return new Student(props || {})
}

这个createStudent()函数有几个巨大的优点:一是不需要new来调用,二是参数非常灵活,可以不传,也可以这么传:


var xiaoming = createStudent({
  name: '小明'
});

xiaoming.grade; // 1

如果创建的对象有很多属性,我们只需要传递需要的某些属性,剩下的属性可以用默认值。由于参数是一个Object,我们无需记忆参数的顺序。如果恰好从JSON拿到了一个对象,就可以直接创建出xiaoming。

练习

请利用构造函数定义Cat,并让所有的Cat对象有一个name属性,并共享一个方法say(),返回字符串'Hello, xxx!':

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

The above is the detailed content of Detailed introduction to creating objects in JavaScript. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn