一看就会的JS基础

1.创建对象

1.1 创建对象的方式

  • Object构造函数
  • 对象字面量

虽然这两种方式可以方便的创建对象,但是在创建具有同样接口的多个对象时,需要重复编写很多代码。

1.2 工厂模式

js 复制代码
function createPerson(name, age, job) {
      let o = new Object();
      o.name = name;
      o.age = age;
      o.job = job;
      o.sayName = function () {
        console.log("我的名字是", this.name);
      };
      return o;
    }

    let person1 = createPerson("狗蛋", 23, "Softwrae Engineer");
    let person2 = createPerson("翠花", 18, "Doctor");
    console.log("person1", person1);
    console.log("person2", person2);

函数createPerson()接收三个参数,每次调用都会返回三个属性和一个方法的对象,虽然工厂模式可以解决创建多个类似对象的问题,但是没有解决对象的标识问题(新创建的对象是什么类型)。

1.3 构造函数模式

ECMAScript中的构造函数是用来创建特定类型对象的,像Object、Array这样的原生构造函数可以直接使用,当然我们也可以自定义构造函数

js 复制代码
function Student(name, age, job) {
  // let o = new Object(); 不用显示地创建对象
  // 属性和方法直接赋值给this
  this.name = name;
  this.age = age;
  this.job = job;
  this.sayName = function () {
    console.log("我的名字是", this.name);
  };
  //   return o; 不需要return
}
let student1 = new Student("狗蛋", 23, "Softwrae Engineer");
let student2 = new Student("翠花", 18, "Doctor");
console.log("student1", student1);
console.log("student2", student2);

注意: 函数名Student首字母大写(按照惯例),用于区分普通函数和构造函数。

要创建Student实例,应使用new操作符,创建实例对象的过程,构造函数做了什么?

js 复制代码
在内存中创建一个新对象
在这个新对象内部的 [[Prototype]] 特性被赋值为构造函数的prototype属性
构造函数内部的this被赋值为这个新对象(即this指向这个新对象)
执行构造函数内部的代码(给新对象赋值)
如果构造函数返回非空对象,则返回该对象;否则返回刚创建的新对象

student1 和 student2都保存着Student的不同实例,这两个对象都有一个constructor属性指向Student

js 复制代码
    console.log(student1.constructor === Student); // true
    console.log(student2.constructor === Student); // true

constructor本来是用来标识对象类型的,但是一般认为instanceof操作符是确定对象类型更可靠的方式。

js 复制代码
console.log(student1 instanceof Student); // true
console.log(student1 instanceof Object); // true
console.log(student2 instanceof Student); // true
console.log(student2 instanceof Object); // true

自定义构造函数可以确保实例被标识为特定类型,这里student1和student2之所以也被认定为Object的实例,是因为所有自定义对象都继承自Object。

值得注意的是:构造函数不一定要写成函数声明式,同时也可以写成赋值给变量的函数表达式、在实例化时如果不传参数,可以不写括号,只要有new操作符就可以调用相应的构造函数。

1.4构造函数也是函数

构造函数与函数的区别是:调用方式不同,任何函数只要使用new操作符来调用就是构造函数,否则就是普通函数。

js 复制代码
// 作构造函数
let student1 = new Student("狗蛋", 23, "Softwrae Engineer");
student1.sayName(); // 我的名字是 狗蛋
// 作为函数调用
Student("狗蛋2", 23, "Softwrae Engineer"); // 添加到window对象
window.sayName(); // 我的名字是 狗蛋2
// 在另一个对象的作用域中调用
let person = new Object();
Student.call(person, "狗蛋爸爸", "35", "teacher");
person.sayName(); // 我的名字是 狗蛋爸爸

从上面三个例子可以得知:

  • 没有使用new操作符调用,属性和方法会添加到window对象
  • 说明this默认是指向全局Global对象的,浏览器中就是window对象
  • 通过call()/apply()调用函数,可以改变this的指向

1.5 构造函数的问题

构造函数的问题在于,其定义的方法会在每个实例都创建一遍,比如如下代码:

js 复制代码
function Student(name, age, job) { 
// let o = new Object(); 不用显示地创建对象 
// 属性和方法直接赋值给this this.name = name;
this.age = age; 
this.job = job; 
this.sayName = function () { 
console.log("我的名字是", this.name); 
}; 
// return o; 不需要return
} 
let student1 = new Student("狗蛋", 23, "Softwrae Engineer"); 
let student2 = new Student("翠花", 18, "Doctor");

student1和student2都有名为sayName的方法,但是它们不是同一个Function实例。在ECMAScript中函数就是对象,每次定义函数都会初始化一个对象。因此,不同实例上的函数虽然同名但却不相等。

js 复制代码
console.log(student1.sayName === student2.sayName); // false

所以,都是做同样的事情,所以没有必要定义两个不同的Function实例。

我们可以尝试将函数定义在构造函数的外部:

js 复制代码
function Student(name, age, job) {
  this.name = name;
  this.age = age;
  this.job = job;
  this.sayName = sayName;
}
function sayName(name) {
  console.log("我的名字是", this.name);
}
let student1 = new Student("狗蛋", 23, "Softwrae Engineer");
let student2 = new Student("翠花", 18, "Doctor");
student1.sayName(); // 我的名字是 狗蛋
student2.sayName(); // 我的名字是 翠花

这样就能解决相同逻辑的函数重复定义的问题,但是这样全局作用域会因此变得混乱,因为这个函数只能在一个对象上调用,如果该对象需要多个方法,那么就要在全局作用域中定义多个函数,这样代码会非常的分散。这个问题可以通过原型模式来解决!待续......

相关推荐
惜.己28 分钟前
javaScript基础(8个案例+代码+效果图)
开发语言·前端·javascript·vscode·css3·html5
长天一色1 小时前
【ECMAScript 从入门到进阶教程】第三部分:高级主题(高级函数与范式,元编程,正则表达式,性能优化)
服务器·开发语言·前端·javascript·性能优化·ecmascript
NiNg_1_2341 小时前
Vue3 Pinia持久化存储
开发语言·javascript·ecmascript
读心悦1 小时前
如何在 Axios 中封装事件中心EventEmitter
javascript·http
神之王楠2 小时前
如何通过js加载css和html
javascript·css·html
余生H2 小时前
前端的全栈混合之路Meteor篇:关于前后端分离及与各框架的对比
前端·javascript·node.js·全栈
流烟默2 小时前
Vue中watch监听属性的一些应用总结
前端·javascript·vue.js·watch
茶卡盐佑星_3 小时前
meta标签作用/SEO优化
前端·javascript·html
与衫3 小时前
掌握嵌套子查询:复杂 SQL 中 * 列的准确表列关系
android·javascript·sql
金灰3 小时前
HTML5--裸体回顾
java·开发语言·前端·javascript·html·html5