Front-end Architect 08_JavaScript Object

1 Overview of object-oriented

1.1 Process-oriented and object-oriented

  • Process-oriented: The focus is on the specific steps to complete the task. Only by following the steps step by step can the task be completed.
    • For process-oriented thinking, we play the role of executors and everything must be completed by ourselves.
    • The disadvantage of process-oriented thinking is that the codes written are all variables and functions. As the function of the program continues to increase, there will be more and more variables and functions. At this time, it is easy to encounter the problem of naming conflicts. Since the codes for various functions Intertwined together, the code structure becomes confusing and difficult to understand, maintain and reuse.
  • Object-oriented: The focus is on each object. These objects perform their own duties. As long as we give orders, we can direct these objects to help us complete the task.
    • For object-oriented thinking, we play the role of commander. We only need to find the corresponding objects and let them do specific things for us.
    • The advantage of object-oriented thinking is that the operation codes of the same type of things can be encapsulated into objects, and the variables and functions used can be used as attributes and methods of the objects, and then called through the objects. This can make the code structure clear and hierarchical.

1.2 Object-oriented features

Encapsulation
  • It refers to hiding the internal implementation details and only opening the operation interface to the outside world.
  • Usage: It is the method of the object. No matter how complex the object is internally, the user only needs to know how to use these interfaces.
  • Advantages: No matter how many times the code inside an object is modified, as long as the interface is not changed, the code written when using this object will not be affected.
  • Computers are very high-precision electronic devices, and their implementation principles are also very complex. Users do not need to know these details when using them. They can use them as long as they operate the keyboard and mouse.
inheritance
  • It means that one object inherits the members of another object and can be extended without changing the other object.

  • The String object is an abstraction of all strings. All strings have the toUpperCase() method, which is used to convert the string to uppercase. This method is actually inherited from the String object.

  • Advantages: Functions can be expanded while maintaining interface compatibility. It enhances the reusability of code and provides convenience for program modification and addition.

polymorphism
  • It means that the same operation will produce different execution results when applied to different objects.

  • In fact, JavaScript is designed as a weakly typed language (that is, a variable can store any type of data), which is the embodiment of polymorphism.

  • Numbers, arrays, and functions all have toString() methods. When this method is called using different objects, the execution results are different.

    var obj = 123;
    console.log(obj.toString());	// 输出结果:123
    obj = [1, 2, 3];
    console.log(obj.toString());	// 输出结果:1,2,3
    obj = function() {
          
          };
    console.log(obj.toString());	// 输出结果:function () {}
    
  • In object-oriented, the implementation of polymorphism is often inseparable from inheritance. This is because when multiple objects inherit the same object, they obtain the same method, and then the execution of the method with the same name is changed according to the difference of each object. result.

Although object-oriented has design ideas such as encapsulation, inheritance, and polymorphism, it does not mean that as long as these characteristics are met, an excellent program can be designed. Developers also need to consider how to use these characteristics reasonably.

  • When encapsulating, how to provide a complete and minimal interface to external callers, so that external callers can smoothly get the desired functions without studying its internal details.
  • When doing inheritance and polymorphic design, how to design a set of identical methods to operate on multiple different sub-objects that inherit the same object.

2 What is an object

2.1 Real-life objects

Everything is an object, and an object is a specific thing, something that can be seen and touched. A specific thing will have behaviors and characteristics. For example, a car, a mobile phone, and a person are all objects.

Mobile phone attributes: color, weight, screen size.

Methods on mobile phones: making calls, sending text messages, watching videos, and listening to music.

2.2 Objects in JavaScript

The object in JavaScript is actually an abstraction of specific things in life.

A JavaScript object is an unordered collection of properties that can contain basic values, objects, or functions. An object is a set of values ​​without order. We can think of objects in JavaScript as key-value pairs, where the values ​​can be data and functions.

Object behavior and characteristics

  • Characteristics—Attributes
    • The characteristics of things are represented by attributes in objects.
  • behavior-method
    • The behavior of things is represented by methods in objects.

Note: Javascript is an object-based language. In JavaScript, any value that is not a numeric value, a string, a Boolean value, a symbol, null and undefined is an object.

3 Object classification

Objects belong to composite data types, and there are three types, namely:

  • built-in objects
    • Objects built into the ES standard can be used in any ES implementation, such as Math, String, Boolean, Number, Function, Object…
  • host object
    • The objects provided by the environment where js runs generally refer to the browser, such as DOM, BOM...
  • custom object
    • Objects customized by the developer

4 Custom objects

4.1 Definition of objects

Syntax: The definition of objects is achieved through the "{ }" syntax.

Composition: The object is composed of object members (properties and methods), and multiple members are separated by commas.

Members: The members of the object are stored in {} in the form of key-value pairs.

var o1 = {
    
    };
var o2 = {
    
    name: 'Jim'};
var o3 = {
    
    name: 'Jim', age: 19, gender: '男'};
var o4 = {
    
    
    name: 'Jim',
    age: 19,
    gender: '男',
    sayHello: function() {
    
    
        console.log('你好');
    }
};

"{ }" syntax is also called object literal syntax. The so-called literal refers to a quantity representing data and type written directly in the source code, such as 123 (numeric type), '123' (character type), [ 123] (arrays) are all literals.

JSON data format

JSON: JavaScript Object Notation, JavaScript object notation.

Purpose: Used for data storage and interaction.

Syntax: JSON is a string, using double quotes to wrap the member name of the object and the string value.

The difference between JSON and objects:

  • JSON is a string.
  • JSON can be used not only to save objects, but also to save other types of data such as numbers, strings, arrays, etc.
{
    
    "name":"Tom","age":24,"work":true,"arr":[1,2]}
// 或
[{
    
    "name":"Tom","age":24},{
    
    "name":"Jim","age":25}]

4.2 Access object members

Syntax: object.member.

var o5 = {
    
    };                           // 创建一个空对象
o5.name = 'Jack';                      // 为对象增加属性
o5.introduce = function () {
    
               // 为对象增加方法
    alert('My name is ' + this.name);  // 在方法中使用this代表当前对象
};
alert(o5.name);                        // 访问name属性,输出结果:Jack
o5.introduce();                        // 调用introduce()方法,输出结果:My name is Jack

Variable member name syntax: object [variable name] = value.

var o6 = {
    
    };		// 创建一个空对象
var key = 'id';		// 通过变量保存要操作的属性名
o6[key] = 123;		// 相当于“o6['id'] = 123”或“o6.id = 123”

4.3 Object member traversal

Syntax: for…in.

var obj = {
    
    name: 'Tom', age: 16};
for (var k in obj) {
    
    
    console.log(k + '-' + obj[k]);
}
  • The variable k holds the name of each object member.
  • obj[k]Access the value of a member property.
  • obj[k]()Call member methods.
Determine whether object members exist
  • When you need to determine whether a member of an object exists, you can use the in operator.
  • Returns true when the member of the object exists, returns false when it does not exist.
var obj = {
    
    name: 'Tom', age: 16};
console.log('name' in obj);    // 输出结果:true
console.log('gender' in obj);  // 输出结果:false

4.4 Deep copy and shallow copy

Copy: refers to copying a target data to form two individuals.

Deep copy: Two targets participate in the copy. Changing the value of one target will not affect the value of the other target.

Shallow copy: Two targets participate in the copy. If the value of one target changes, the value of the other target will also change accordingly.

  • Shallow copy only copies one layer, deeper object level only copies references.
  • Deep copy copies multiple layers, and data at each level is copied.
  • Object.assign(target,…sources) ES6 new method can shallow copy

How to distinguish between deep copy and shallow copy? To put it simply, it is assumed that B copies A. When A is modified, see whether B will change. If B also changes, it means that this is a shallow copy. The person holding the copy is short-handed. If B has not changed, that is, a deep copy, and it will be self-reliant.

Implement deep copy
  • Basic types (such as numeric and character types): This can be achieved through variable assignment.
  • Reference types (such as arrays, objects): Copy members of an object to another object.
// 深拷贝拷贝多层,每一级别的数据都会拷贝
var obj = {
    
    
    id: 1,
    name: 'andy',
    msg: {
    
    
        age: 18
    }
    color: ['pink','red']
};
var o = {
    
    };
// 封装函数
function deepCopy(newobj,oldobj){
    
    
    for(var k in oldobj){
    
    
        // 判断属性值属于简单数据类型还是复杂数据类型
        // 1.获取属性值   oldobj[k]
        var item = oldobj[k];
        // 2.判断这个值是否是数组
        if(item instanceof Array){
    
    
            newobj[k] = [];
            deepCopy(newobj[k],item)
        }else if (item instanceof Object){
    
    
            // 3.判断这个值是否是对象
            newobj[k] = {
    
    };
            deepCopy(newobj[k],item)
        }else {
    
    
            // 4.属于简单数据类型
            newobj[k] = item;
        } 
    }
}
deepCopy(o,obj);

Note: JSON.parse( JSON.stringify(obj)); can also implement deep copy. It should be noted that the deep copy implemented by this method cannot copy function, undefined, and symbol.

Implement shallow copy
  • Reference types (such as arrays, objects): This can be achieved through variable assignment.
  • Tip: Shallow copy is a concept only found in reference types.
// 浅拷贝只是拷贝一层,更深层次对象级别的只拷贝引用
var obj = {
    
    
    id: 1,
    name: 'andy',
    msg: {
    
    
        age: 18
    }
};
var o = {
    
    }
for(var k in obj){
    
    
    // k是属性名,obj[k]是属性值
    o[k] = obj.[k];
}
console.log(o);
// 浅拷贝语法糖
Object.assign(o,obj);
Advantages of Shallow Copy

Shallow copy can save memory overhead.

5 Constructor

5.1 Why use constructors

Constructors are another way to create objects in JavaScript.

Contrast with creating objects using literal methods: Constructors can create some objects with the same characteristics.

For example, create apple, banana, and orange objects through the fruit constructor. Its characteristic is that these objects are all created based on the same template, and each object has its own characteristics.

Characteristics of creating objects using literals

  • Advantages: Simple and flexible.
  • Disadvantage: When you need to create a set of objects with the same characteristics, you cannot specify through code which members these objects should have in common.

The way to implement templates in object-oriented programming languages ​​is to use classes to create templates and implement different objects (instances of classes) based on the templates.

  • Method 1 for implementing templates in JavaScript: through a factory function, which creates an object using the literal "{ }" inside it. The disadvantage is that the type of the object cannot be distinguished.
  • Method 2 of JavaScript implementation of templates: Create objects through constructors.

5.2 JavaScript built-in constructors

JavaScript built-in constructors

  • Common built-in constructors: Object, String, Number and other constructors.

How the constructor creates objects: new constructor name ().

The process of creating an object using the new keyword is called instantiation, and the object obtained after instantiation is called an instance of the constructor.

// 通过构造函数创建对象
var obj = new Object();         // 创建 Object 对象
var str = new String('123');    // 创建 String 对象
// 查看对象是由哪个构造函数创建的
console.log(obj.constructor);   // 输出结果:function Object() { [native code] }
console.log(str.constructor);   // 输出结果:function String() { [native code] }
console.log({
    
    }.constructor);    // 输出结果:function Object() { [native code] }
  • The "object.constructor" property points to the constructor of the object.
  • When output through console.log(), [native code] indicates that the code of the function is built-in

5.3 Custom constructor

  • It is recommended to use the Pascal naming rule for naming constructors, that is, capitalize the first letter of all words.
  • Inside the constructor, let this represent the object just created.
// 自定义构造函数
function Person(name, age) {
    
    
    this.name = name;
    this.age = age;
    this.sayHello = function () {
    
    
        console.log('Hello, my name is ' + this.name);
    };
}

// 使用构造函数
var p1 = new Person('Jack', 18);
var p2 = new Person('Alice', 19);
console.log(p1);		
console.log(p2);		
p1.sayHello();
console.log(p1.constructor);

Notice:

  • In JavaScript, people are often confused by some similar terms, such as function, method, constructor, constructor, constructor, etc.
  • In fact, they can all be collectively called functions, but they have different names in different usage scenarios. By convention, functions defined in an object are called methods of the object.
  • For constructors, some people are accustomed to calling them constructors or constructors. We only need to understand that these names refer to the same thing.
ES6’s new class keyword
  • The reason why it didn’t exist before ES6: To simplify the difficulty.
  • Reason for adding: With the development of Web front-end technology, some people who were originally engaged in back-end development turned to the front-end. In order to make JavaScript closer to the syntax of some back-end languages ​​so that developers can adapt faster.
  • The role of the class keyword: used to define a class.
  • Features: The constructor constructor method can be defined in the class.

Note: The class syntax is essentially syntactic sugar, and is only designed for user convenience. The same effect can be achieved without using this syntax, such as the constructor learned earlier. In case the user's browser does not support this syntax, this method is not recommended.

5.4 Private members

In a constructor, variables defined using the var keyword are called private members.

Features: After the instance object, it cannot be accessed through "object.member", but private members can be accessed in the member method of the object.

Features: The private member name reflects object-oriented encapsulation.

function Person() {
    
    
    var name = 'Jim';
    this.getName = function () {
    
    
        return name;
    };
}
var p = new Person();    // 创建实例对象p
console.log(p.name);     // 访问私有成员,输出结果:undefined
p.getName();             // 访问对外开放的成员,输出结果:Jim
return keyword in constructor

The essence of the constructor is a function, so the return keyword can also be used in the constructor.

There are certain differences between constructors and ordinary functions when used:

  • If return is used to return reference type data such as an array or object, the constructor returns the data directly without returning the originally created object.
  • If basic type data is returned, the returned data is invalid and the originally created object will still be returned.
// 返回基本类型数据
function Person() {
    
    
    obj = this;
    return 123;
}
var obj, p = new Person();
console.log(p === obj);   // true

// 返回引用类型数据
function Person() {
    
    
    obj = this;
    return {
    
    };
}
var obj, p = new Person();
console.log(p === obj);   // false

5.5 This point in the function

Characteristics of this: Depending on how the function is called, the this pointer in the function will change.

this-oriented

In JavaScript, this pointer within a function is usually related to the following three situations.

  • When the new keyword calls a function as a constructor, this inside the constructor points to the newly created object.
  • When calling a function directly through the function name, this points to the global object (the window object in the browser).
  • If the function is called as a method of an object, this will point to the object.
function foo() {
    
    
    return this;
}
var o = {
    
    name: 'Jim', func: foo};
console.log(foo() === window);    // 输出结果:true
console.log(o.func() === o);      // 输出结果:true
Change this to point to

In addition to following the default this pointing rules, the caller of the function can also use the two methods provided by JavaScript to manually control the pointing of this.

  • apply() method
  • call() method
function method() {
    
    
    console.log(this.name);
}
// 输出结果:张三
method.apply({
    
    name: '张三'}); 
// 输出结果:李四
method.call({
    
    name: '李四'});


function method(a, b) {
    
    
    console.log(a + b);
}
// 数组方式传参,输出结果:12
method.apply({
    
    }, ['1', '2']); 
// 参数方式传参,输出结果:34
method.call({
    
    }, '3', '4');

Summarize:

  • Similarity: The first parameter of the apply() and call() methods indicates which object this points to.
  • Differences: The second parameter of the apply() method represents the parameter passed in when calling the function, which is passed in the form of an array; the second to N parameters of the call() method represent the function passed in when calling the function.
ES5’s new bind() method
  • The role of the bind() method: It is used to specify the meaning of this before calling the function to achieve the effect of early binding.
  • The first parameter of the bind() method: the object to which this points.
  • The 2nd~N parameters of the bind() method: represent the function passed in when calling the function.
function method(a, b) {
    
    
    console.log(this.name + a + b);
}
var name = '张三';
var test = method.bind({
    
    name: '李四'}, '3', '4');
method('1', '2');    // 输出结果:张三12
test();              // 输出结果:李四34

6 built-in objects

6.1 String object

  • Creation of character data: Use a pair of single quotes or double quotes.

  • Why can character data be used like objects? This is because these objects are actually instances of the constructor String, that is, String objects.

  • The String object provides some properties and methods for processing strings.

member effect
length Get the length of a string
charAt(index) Get the character at index position, the position is calculated from 0
indexOf(searchValue) Get the first occurrence of searchValue in a string
lastIndexOf(searchValue) Get the last position of searchValue in the string
substring(start[, end]) Intercept a substring from the start position to the end position
substr(start[, length]) Intercept the substring starting from the start position to the length length
toLowerCase() Get the lowercase form of a string
toUpperCase() Get the uppercase form of a string
split([separator[, limit]) Use the separator delimiter to separate the string into an array, and limit is used to limit the number
replace(str1, str2) Use str2 to replace str1 in the string and return the replacement result

When operating on a string, the processing result is returned directly through the return value of the method and does not change the string content stored in the String object itself. In the parameters of these methods, the position is an index value, counting from 0, the index value of the first character is 0, and the index value of the last character is the length of the string minus 1.

// 限制用户名长度在3~10范围内,不允许出现敏感词admin
var name = 'Administrator';
if (name.length < 3 || name.length > 10) {
    
    
    alert('用户名长度必须在3~10之间。');
}
if (name.toLowerCase().indexOf('admin') !== -1) {
    
    
    alert('用户名中不能包含敏感词:admin。');
}

6.2 Number object

Number objects are used to process numerical values ​​such as integers and floating point numbers. Commonly used properties and methods are as follows.

member effect
MAX_VALUE The maximum value that can be represented in JavaScript (static member)
MIN_VALUE The smallest positive value that can be represented in JavaScript (static member)
toFixed(digits) Format a numeric value using fixed-point notation
var num = 12345.6789;
num.toFixed();       // 四舍五入,不包括小数部分,返回结果:12346
num.toFixed(1);      // 四舍五入,保留1位小数,返回结果:12345.7
num.toFixed(6);      // 用0填充不足的小数位,返回结果:12345.678900
Number.MAX_VALUE;    // 获取最大值,返回结果:1.7976931348623157e+308
Number.MIN_VALUE;    // 获取最小正值,返回结果:5e-324

It is a static member of Number and is accessed directly through the constructor Number, rather than an instance of Number.

6.3 Math object

The Math object is used to perform mathematical operations on numerical values. Unlike other objects, this object is not a constructor and does not need to be instantiated to be used.

member effect
PI Get pi, the result is 3.141592653589793
abs(x) Get the absolute value of x, you can pass in an ordinary value or a value represented by a string
max([value1[,value2, …]]) Get the maximum value among all parameters
min([value1[,value2, …]]) Get the minimum value among all parameters
pow(base, exponent) Get the exponent power of the base (base), that is, baseexponent
sqrt(x) Get the square root of x
ceil(x) Get the smallest integer greater than or equal to x, that is, round up
floor(x) Get the largest integer less than or equal to x, that is, round down
round(x) Gets the rounded integer value of x
random() Get a random value greater than or equal to 0.0 and less than 1.0

The formula is Math.random() * (n - m) + m, which means generating a random value greater than or equal to m and less than n

Math.random() * (3 - 1) + 1;       //  1 ≤ 返回结果 < 3
Math.random() * (20 - 10) + 10;    // 20 ≤ 返回结果 < 20
Math.random() * (99 - 88) + 88;    // 88 ≤ 返回结果 < 99
Math.floor(Math.random() * (3- 1+ 1) + 1);    // 返回结果 是1、2、3中的任意一个

6.4 Date object

Date object is used to handle date and time.

member effect
getFullYear() Get the 4-digit number representing the year, such as 2020
setFullYear(value) Set year
getMonth() Get the month, ranging from 0 to 11 (0 means January, 1 means February, and so on)
setMonth(value) Set month
getDate() Get the day of the month, range 1~31
setDate(value) Set a day of the month
getDay() Get the day of the week, ranging from 0 to 6 (0 means Sunday, 1 means Monday, and so on)
getHours() Get the number of hours, return 0~23
setHours(value) Set hours
getMinutes() Get the number of minutes, range 0~59
setMinutes(value) Set minutes
getSeconds() Get the number of seconds, range 0~59
setSeconds(value) Set seconds
getMilliseconds() Get the number of milliseconds, ranging from 0 to 999
setMilliseconds(value) Set milliseconds
getTime() Get the number of milliseconds from 1970-01-01 00:00:00 to the time represented by the Date object
setTime(value) Set the time by the number of milliseconds since 1970-01-01 00:00:00
// 根据Date对象获取时间日期
var date = new Date();    // 基于当前时间创建Date对象
// 结果:Fri Oct 06 2017 11:53:04 GMT+0800 (中国标准时间)
date.toString();
date.getFullYear();       // 结果:2017
date.getMonth();          // 结果:9
date.getDate();           // 结果:6

// 根据Date对象指定一个日期
// 方式1:分别传入年、月、日、时、分、秒(月的范围是0~11,即真实月份-1)
var date1 = new Date(2017, 9, 1, 11, 53, 4);
date1.toString();	// 返回结果:Sun Oct 01 2017 11:53:04 GMT+0800 (中国标准时间)
// 方式2:通过字符串传入日期和时间
var date2 = new Date('2017-10-01 11:53:04');
date2.toString();	// 返回结果:Sun Oct 01 2017 11:53:04 GMT+0800 (中国标准时间)

// 处理设置的日期不合理的情况,如将月份设为-1表示去年12月,月份为12表示明年1月
new Date('2017');        // Sun Jan 01 2017 08:00:00 GMT+0800 (中国标准时间)
new Date(2017, 9);       // Sun Oct 01 2017 00:00:00 GMT+0800 (中国标准时间)
new Date(2017, -1);      // Thu Dec 01 2016 00:00:00 GMT+0800 (中国标准时间)
new Date(2017, 12);      // Mon Jan 01 2018 00:00:00 GMT+0800 (中国标准时间)
new Date(2017, 0, 0);    // Sat Dec 31 2016 00:00:00 GMT+0800 (中国标准时间)

6.5 Practice Assignments

  • Make an annual calendar
    • Use the prompt() function to receive the year set by the user.
    • Write the calendar() function to generate an annual calendar based on the specified year.
    • Design and output calendar display style.
    • Get the weekday value on January 1st of the specified year and get the number of days in each month.
    • Loop through the days of each month.
    • Display the date below the corresponding week.

7 Error handling and code debugging

7.1 Error handling

When writing JavaScript programs, you often encounter various errors.

Methods that do not exist are called, variables that do not exist are referenced, etc.

var o = {
    
    };
// 发生错误此句不会执行。
o.func();
console.log('test');

When an error occurs, the JavaScript engine throws an error object.

Error handling: The try...catch statement can capture the error object, and the error information can be viewed after capture.

try {
    
    
    o.func();
    console.log('a');
} catch(e) {
    
    
    console.log(e);
}
console.log('b');

Notice:

  • If there are multiple lines of code in try, as long as an error occurs in one of the lines, the following code will not be executed; if the error has been handled, the code following catch will continue to execute. It can be seen that the amount of code written in try should be as small as possible to avoid the impact when an error occurs.
  • 在以 Java 为代表的编程语言中,引入了异常(Exception)的概念,利用 try…catch 进行异常处理。JavaScript 错误处理的设计思想与之类似,因此也可以将 JavaScript 中的 try…catch 称为异常处理。

7.2 错误对象

在发生错误时,错误出现的位置、错误的类型,错误信息等数据,都会被封装起来,以一个对象的形式传递给 catch 语句,通过 catch(e)的方式来接收,其中 e 是错误对象的变量名。

错误对象会在函数之间传递

  • 当 try 中的代码调用了其他函数时,如果在其他函数中出现了错误,且没有使用 try…catch 处理时,程序就会停下来。
  • 将错误传递到调用当前函数的上一层函数,如果上一层函数仍然没有处理,则继续向上传递。
function foo1() {
    
    
    foo2();
    console.log('foo1');
}
function foo2() {
    
    
    var o = {
    
    }; 
    o.func();   // 发生错误
}

try {
    
    
    foo1();
} catch(e) {
    
    
    console.log('test');
}

手动抛出错误对象

除了在 JavaScript 程序出现错误时自动抛出错误对象,用户也可以使用 throw 关键字手动抛出错误对象。

try {
    
    
    var e1 = new Error('错误信息');
    throw e1;
} catch (e) {
    
    
    console.log(e.message);
    console.log(e1 === e);
}

7.3 错误类型

在 JavaScript 中,共有7种标准错误类型,每个类型都对应一个构造函数。当发生错误时,JavaScript 会根据不同的错误类型抛出不同的错误对象。

类型 说明
Error 表示普通错误,其余6种类型的错误对象都继承自该对象
EvalError 调用eval()函数错误,已经弃用,为了向后兼容,低版本还可以使用
RangeError 数值超出有效范围,如“new Array(-1)”
ReferenceError 引用了一个不存在的变量,如“var a = 1; a + b;”(变量b未定义)
SyntaxError 解析过程语法错误,如“{ ; }”“if()”“var a = new;”
TypeError 变量或参数不是预期类型,如调用了不存在的函数或方法
URIError 解析URI编码出错,调用encodeURI()、escape()等URI处理函数时出现

在通过 try…catch 来处理错误时,无法处理语法错误(SyntaxError)。如果程序存在语法错误,则整个代码都无法执行。

7.4 代码调试

在控制台中执行 JavaScript 代码

单步调试

调试按钮 说明
暂停按钮 暂停或继续执行脚本
下一步按钮1 执行下一步。遇到函数时,不进入函数直接执行下一步
下一步按钮2 执行下一步。遇到函数时,进入函数执行
跳出按钮 跳出当前函数
停用按钮 停用或启用断点
停止按钮 是否暂停错误捕获
调试工具 说明
Watch 可以对加入监听列表的变量进行监听
Call Stack 函数调用堆栈,可以在代码暂停时查看执行路径
Scope 查看当前断点所在函数执行的作用域内容
Breakpoints 查看断点列表
XHR Breakpoints 请求断点列表,可以对满足过滤条件的请求进行断点拦截
DOM Breakpoints DOM断点列表,设置DOM断点后满足条件时触发断点
Global Listeners 全局监听列表,显示绑定在window对象上的事件监听
Event Listener Breakpoints 可断点的事件监听列表,可以在触发事件时进入断点

8 原型与继承

8.1 原型

如何让两个对象共同拥有一份相同的属性和方法?

可通过原型对象来解决。

原理:利用原型对象可以保存一些公共的属性和方法。当访问某个对象中的一个不存在的属性或方法时,会自动调用原型中的属性和方法。也就是说,基于原型创建的对象会自动拥有原型的属性和方法。

在JavaScript中,每定义一个函数,就随之有一个对象存在,函数通过prototype属性指向该对象。这个对象称之为原型对象,简称原型。

function Person() {
    
    }                   // 定义函数
console.log(typeof Person.prototype);  // 输出结果:object
  • Person函数的prototype属性指向的对象,就是Person的原型对象。
  • 在利用构造函数创建对象时,每个对象都默认与这个原型对象连接,连接后就可以访问到原型对象中的属性和方法。

8.2 继承

在现实生活中,继承一般指的是子女继承父辈的财产。

在JavaScript中,继承是在已有对象的基础上进行扩展,增加一些新的功能,得到一个新的对象。

在JavaScript中,提供了四种实现继承的方式。

  • 利用原型对象实现继承
  • 替换原型对象实现继承
  • 利用 Object.create() 实现继承
  • 混入继承
利用原型对象实现继承
function Person(name) {
    
    
    this.name = name;
}
Person.prototype.sayHello = function () {
    
    
    console.log('你好,我是' + this.name);
}

var p1 = new Person('Jim');
var p2 = new Person('Tom');
// 输出结果:你好,我是Jim
p1.sayHello();
// 输出结果:你好,我是 Tom
p2.sayHello();
替换原型对象实现继承
function Person() {
    
    }
Person.prototype = {
    
    
    sayHello: function () {
    
    
        console.log('你好,我是新对象');
    }
}
var p = new Person();
p.sayHello();

注意:在基于构造函数创建对象时,代码应写在替换原型对象之后,否则创建的对象仍然会继承原来的原型对象。

利用 Object.create() 实现继承
var obj = {
    
    
    sayHello: function(){
    
    
        console.log('我是一个带有sayHello方法的对象');
    }
};
// 将obj作为newObj对象的原型
var newObj = Object.create(obj);
混入继承
  • 混入就是将一个对象的成员加入到另一个对象中,实现对象功能的扩展。
  • 实现混入继承最简单的方法就是将一个对象的成员赋值给另一个对象。
var o1 = {
    
    };
var o2 = {
    
    name: 'Jim'};
o1.name = o2.name;     // o1继承o2的name属性
console.log(o1.name);  // 输出结果:Jim
  • 当对象的成员比较多时,如果为每个成员都进行赋值操作,会非常麻烦。
  • 因此编写一个函数专门实现对象成员的赋值,函数通常命名为mix(混合)或extend(扩展) 。
function extend(o1, o2) {
    
    
    for (var k in o2) {
    
    
        o1[k] = o2[k];
    }
}

var o1 = {
    
    name: 'Jim'};
var o2 = {
    
    age: 16, gender: 'male'};
extend(o1, o2);
console.log(o1.name);
console.log(o1.age);

混入式继承和原型继承还可以组合在一起使用,实现以对象的方式传递参数,或以对象的方式扩展原型对象的成员。

8.3 静态成员

静态成员:指由构造函数所使用的成员。

实例成员:指由构造函数创建的对象所使用的成员。

// 实例成员
function Person(name) {
    
    
    this.name = name;
    this.sayHello =  function() {
    
    
        console.log(this.name);
    };
}
var p = new Person('Tom');
console.log(p.name);
p.sayHello();	

// 静态成员
function Person(){
    
    }
Person.age = 123;
Person.sayGood = function() {
    
    
    console.log(this.age);
};
console.log(Person.age);
Person.sayGood();

实际开发中,对于不需要创建对象即可访问的成员,推荐将其保存为静态成员。

比如:构造函数的prototype属性就是一个静态成员,可以在所有实例对象中共享数据。

8.4 属性搜索原则

属性搜索原则只对属性的访问操作有效,对于属性的添加或修改操作,都是在当前对象中进行的。

8.5 原型链

在JavaScript中,对象有原型对象,原型对象也有原型对象,这就形成了一个链式结构,简称原型链。

对象的构造函数

在原型对象中,存在一个constructor属性,指向该对象的构造函数。

function Person() {
    
    }
Person.prototype.constructor === Person;

function Person() {
    
    }
new Person().constructor === Person;
对象的原型对象
  • 对象可以通过constructor属性访问构造函数。
  • 构造函数可以通过prototype属性访问原型对象。
  • 因此,对象.constructor.prototype即可访问对象的原型对象。
function Person() {
    
    }
new Person().constructor.prototype === Person.prototype;
函数的构造函数

由于函数本质上就是对象,所以函数也有构造函数。

function Person() {
    
    }
// 返回结果:function Function() { [native code] }
Person.constructor.toString();
Person.constructor === Function;   // 返回结果:true
String.constructor === Function;    // 返回结果:true
Number.constructor === Function;    // 返回结果:true
Object.constructor === Function;    // 返回结果:true
Function.constructor === Function;  // 返回结果:true

总结:

  • 在JavaScript中,自定义函数以及String、Number、Object等内置构造函数的构造函数都是Function函数。
  • Function函数的构造函数是Function自身。

还可以通过实例化Function构造函数的方式来创建函数。该构造函数的参数数量是不固定的,最后一个参数表示用字符串保存的新创建函数的函数体,前面的参数(数量不固定)表示新创建函数的参数名称。

// new Function('参数1', '参数2', …… '参数N', '函数体');
var func = new Function('a', 'b', 'return a + b;');
console.log(func(100, 200));		// 输出结果:300

func(100, 200);
// 相当于
var func = function(a, b) {
    
    
    return a + b;
}
原型对象的原型对象

对象.constructor.prototype,可访问对象的原型对象。

构造函数的prototype属性指向原型对象,原型对象的constructor属性又指回了构造函数,这就构成了一个循环。

通过这种方式无法访问到原型对象的原型对象。

因此,浏览器为对象增加了一个新的属性 __proto__,方法查看对象的原型。

适用范围:一些新版的浏览器,如火狐、Chrome等。

属性特点:由于其不是JavaScript原有属性,因此前后加两个下划线进行区分。

查看位置:在开发人员工具中方便地查看对象的原型。

function Person() {
    
    }
Person.prototype.__proto__;
function Person() {
    
    }
Person.prototype.__proto__ === Object.prototype;  // 返回结果:true
Object.prototype.__proto__;                       // 返回结果:null
Object.__proto__ === Function.prototype;          // 返回结果:true
  • 构造函数Person的原型对象的原型对象,是构造函数Object的原型对象。
  • 构造函数Object的原型对象的原型对象是null。
  • 构造函数Object的原型对象是构造函数Function的原型对象。
原型链的结构
  • 自定义函数,以及Object、String、Number等内置函数,都是由Function函数创建的,Function函数是由Function函数自身创建的。
  • 每个构造函数都有一个原型对象,构造函数通过prototype属性指向原型对象,原型对象通过constructor属性指向构造函数。
  • 由构造函数创建的实例对象,继承自构造函数的原型对象。通过实例对象的 __proto__ 属性可以直接访问原型对象。
  • 构造函数的原型对象,继承自Object的原型对象,而Object的原型对象的 __proto__ 属性为null。

在进行原型操作时,“对象.constructor.prototype”访问到的是该对象当前继承的原型对象的构造函数的原型对象,并不一定是实际构造函数的原型对象。

function Person() {
    
    }
function Func() {
    
    }
Person.prototype = new Func();
var p1 = new Person();
p1.constructor === Func;                      // 返回结果:true
p1.constructor.prototype === Func.prototype;  // 返回结果:true
p1.__proto__ === Person.prototype;            // 返回结果:true
instanceof 运算符

检测一个对象的原型链中是否含有某个构造函数的prototype属性所表示的对象。

返回值:布尔类型,存在返回true,否则返回false。

function Person() {
    
    }
var p1 = new Person();
console.log(p1 instanceof Person);  // 输出结果:true

// 更改构造函数的prototype属性
function Person() {
    
    }
function Func() {
    
    }
var p1 = new Person();
Person.prototype = new Func();
var p2 = new Person();
console.log(p1 instanceof Person);	// 输出结果:false
console.log(p2 instanceof Person);	// 输出结果:true

// 让当前Person.prototype在p1的原型链上
p1.__proto__.__proto__ = Person.prototype;
console.log(p1 instanceof Person);	// 输出结果:true

9 练习作业

  • 输入n,输出n天后的时间

  • 获取两个日期之间相差的天数

  • 使用Math对象随机数实现点名功能

  • 使用String对象实现,对任意字符串敏感字符替换功能

  • 使用工厂函数

    • 创建饮水机对象,饮水机对象有热水和冷水方法,以及饮水机位置属性
    • 创建三个怪物对象,并且输出怪物的名字、性别、等级,怪物执行攻击方法,输出“水球术”
    • 创建一个动漫对象,输出动漫的人物,爱好,性别,能力
  • var data = [
        {
          
           StudentNumber: 2022003, Chinese: 86, Math: 64, English: 80, TotalScore: "", Comment: "" },
        {
          
           StudentNumber: 2022004, Chinese: 78, Math: 99, English: 91, TotalScore: "", Comment: "" },
        {
          
           StudentNumber: 2022005, Chinese: 107.5, Math: 97, English: 70, TotalScore: "", Comment: "" },
        {
          
           StudentNumber: 2022006, Chinese: 112, Math: 61, English: 92, TotalScore: "", Comment: "" },
        {
          
           StudentNumber: 2022007, Chinese: 101, Math: 79, English: 104, TotalScore: "", Comment: "" },
        {
          
           StudentNumber: 2022008, Chinese: 71, Math: 72, English: 105, TotalScore: "", Comment: "" },
        {
          
           StudentNumber: 2022009, Chinese: 56, Math: 68, English: 61, TotalScore: "", Comment: "" },
        {
          
           StudentNumber: 2022010, Chinese: 98, Math: 83, English: 77, TotalScore: "", Comment: "" }
    ];
    
    • 以上是某班级一次考试的成绩表。请计算每个学生总成绩,并按总成绩排名。统计各单科成绩第一名,输出其成绩与学号。
    • 并根据总成绩计算每个学生成绩备注保存在 Comment 中,平均分72分以上为D,90分以上为C,100分以上为B,110分以上为A,72分以下为E
  • 有两个数组,一个数组arr是班级里所有的学员的名称,一个数组currentArr是提交了每日反馈的学员名单,请创建一种算法,把未提交每日反馈的学员筛选出来

  • 创建一个电脑对象,有颜色(color)、重量(weight)、品牌(brand)、型号(type)等属性,有看电影(watch)、听音乐(listen)、打游戏(play)和敲代码(coding)等方法。

    • 颜色、重量、品牌、型号是属性;看电影、听音乐、打游戏、敲代码是方法,在调用方法时分别打印 “我在看电影/听音乐/打游戏/敲代码”
    • 方法保存在原型对象中
  • 使用构造函数创建一个自定义对象,通过自定义对象生成指定行数、列数、宽度和高度的表格。

  • 表单生成器

    • 直接编写HTML表单虽然简单,但修改、维护相对麻烦。

    • 在线考试系统或问卷调查系统,题目和问题的录入的功能。

    • 利用对象保存表格数据。

    • 将表单项看成一个个对象。

    • 归纳表单项的结构模板,包括tag(标签名)、text(提示文本)、attr(标签属性)、option(选项)四个属性。

    • 按照表单数据保存的分析创建对象保存相关数据。

    • 编写FormBuilder对象,接收表单数据,并将结果显示到指定位置上。

    • 编写builder对象,根据传入的数据生成表单项。

    • 编写item对象,根据标签名称生成表单项。

    • var elements = [
          {
              
              tag: 'input', text: '用户名', attr: {
              
              type: 'text', name: 'username'}},
          {
              
              tag: 'input', text: '密码', attr: {
              
              type: 'password', name: 'userpass'}},
          {
              
              tag: 'input', text: '确认密码', attr: {
              
              type: 'password', name: 'userpass_confirm'}},
          {
              
              tag: 'input', attr: {
              
              type: 'submit', value: '提交'}}
      ];
      

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 定义一个对象,new 出来的每一个实例会生成一个彩色气泡,颜色、大小、位置、运动方向都随机设置

    • 颜色数组

    • var color = ["#f83600", "#FFF94C", "#0072ff", "#780206", "#7B920A", "#dc2430", "#A83279", "#00bf8f", "#FF512F", "#485563", "#061700", "#02AAB0"]
      

戏(play)和敲代码(coding)等方法。

  • 颜色、重量、品牌、型号是属性;看电影、听音乐、打游戏、敲代码是方法,在调用方法时分别打印 “我在看电影/听音乐/打游戏/敲代码”

  • 方法保存在原型对象中

  • 使用构造函数创建一个自定义对象,通过自定义对象生成指定行数、列数、宽度和高度的表格。

  • 表单生成器

    • 直接编写HTML表单虽然简单,但修改、维护相对麻烦。

    • 在线考试系统或问卷调查系统,题目和问题的录入的功能。

    • 利用对象保存表格数据。

    • 将表单项看成一个个对象。

    • 归纳表单项的结构模板,包括tag(标签名)、text(提示文本)、attr(标签属性)、option(选项)四个属性。

    • 按照表单数据保存的分析创建对象保存相关数据。

    • 编写FormBuilder对象,接收表单数据,并将结果显示到指定位置上。

    • 编写builder对象,根据传入的数据生成表单项。

    • 编写item对象,根据标签名称生成表单项。

    • var elements = [
          {
              
              tag: 'input', text: '用户名', attr: {
              
              type: 'text', name: 'username'}},
          {
              
              tag: 'input', text: '密码', attr: {
              
              type: 'password', name: 'userpass'}},
          {
              
              tag: 'input', text: '确认密码', attr: {
              
              type: 'password', name: 'userpass_confirm'}},
          {
              
              tag: 'input', attr: {
              
              type: 'submit', value: '提交'}}
      ];
      

      [外链图片转存中…(img-PiwLotxf-1695696232118)]

  • 定义一个对象,new 出来的每一个实例会生成一个彩色气泡,颜色、大小、位置、运动方向都随机设置

    • 颜色数组

    • var color = ["#f83600", "#FFF94C", "#0072ff", "#780206", "#7B920A", "#dc2430", "#A83279", "#00bf8f", "#FF512F", "#485563", "#061700", "#02AAB0"]
      

Guess you like

Origin blog.csdn.net/zhangchen124/article/details/133299678