javascript 中 万物皆对象。 对象只是带有属性和方法的特殊数据类型 对象只是一种特殊的数据。对象拥有属性和方法 js 中的引用类型都派生自 对象(Object),如 Array Function Math 等等 包括 常见的 基本类型(值类型) string 、 number 的值 均为对应的 String 、 Number 调用 valueOf 或者 toString 得到的 可见,对象在 javascript 中的地位。 在 javascript 的世界里,对象就是属性的集合
对象从形式上来定义 JavaScript 的对象,是一种属性的集合。【 属性值可以是 函数(function)】
创建对象使用 对象字面量 创建对象 1 2 3 4 5 6 7 var person = { name: 'mcdowell' , age: 29 , } person.sayName = function ( ) { alert(this .name) }
使用{}创建对象,等同于 new Object();
使用 new 借助 Object 函数 创建对象 1 2 3 4 5 6 var person = new Object ()person.name = 'mcdowell' person.age = 29 person.sayName = function ( ) { alert(this .name) }
问题:1.代码冗余; 2.对象中的方法不能共享,每个对象中的方法都是独立的
使用 工厂模式 创建对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function createPerson (name, age ) { var person = new Object () person.name = name person.age = age person.sayName = function ( ) { alert(this .name) } return person } var p1 = createPerson('mcdowell' , 29 )var p2 = createPerson('bart' , 31 )console .log(p1, 'p1,p2' , p2)console .log(p1.constructor === p2.constructor) console .log(p1.constructor === createPerson) console .log(p1 instanceof Object ) console .log(p2 instanceof Object ) console .log(p1.sayName === p2.sayName)
工厂函数每执行一次,都会创建一个对象。 每个创建的 对象都拥有各自独立的方法和属性 。 对象的 constructor 构造函数共同指向 Object 方法
优点:避免部分代码重复,减少冗余 缺点:每个对象 调用的还是不同的方法 ( 方法没有实现复用 )
通过构造函数 创建对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function Person (name, age ) { this .name = name this .age = age this .sayName = function ( ) { alert(this .name) } } var p1 = new Person('mcdowell' , 29 )var p2 = new Person('bart' , 31 )console .log(p1, 'p1,p2' , p2)console .log(p1.constructor === p2.constructor) console .log(p1.constructor === Person) console .log(p1 instanceof Object ) console .log(p2 instanceof Object ) console .log(p1.sayName === p2.sayName)
每 new 一次 构造函数,都会创建一个对象 每个创建的 对象都拥有各自独立的方法和属性 。 对象的 constructor 构造函数共同指向 Person 方法
优点:进一步优化,避免部分代码重复,减少冗余 缺点:每个对象 调用的还是不同的方法 ( 方法没有实现复用 )
通过 原型模式 创建对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function Person ( ) {}Person.prototype.name = 'person' Person.prototype.sayName = function ( ) { console .log(this .name, 'name' ) } var p1 = new Person()var p2 = new Person()p1.sayName() console .log(p1.sayName === p2.sayName) console .log(Person.prototype.constructor) console .log(Person.prototype.constructor == Person) console .log(p1.__proto__ === p2.__proto__)
每 new 一次 构造函数,都会创建一个对象 每个创建的 对象都 都通过 proto 指向 Person.prototype 对象,从而实现 属性方法共享。 对象的 constructor 构造函数共同指向 Person 方法
优点: 真正意义实现了复用 缺点: 各对象 也需要自己特有属性 方法
通过 原型模式 + 构造函数 创建对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function createPerson (name, age ) { this .name = name this .age = age } createPerson.protoType.sayName = function ( ) { alert(this .name) }; var p1 = new createPerson('mcdowell' , 29 )var p2 = new createPerson('bart' , 31 )console .log(p1, 'p1,p2' , p2)console .log(p1.constructor === p2.constructor) console .log(p1.constructor === createPerson) console .log(p1 instanceof Object ) console .log(p2 instanceof Object ) console .log(p1.sayName === p2.sayName)
优点:每个对象 都会有自己的一份 属性的副本,但又同时共享着对方法的引用,最大限度地节省了内存。 继承:需要复用的放在 protoType 属性指向的对象下 ,通过 原型链 的方式 实现复用 多态:不同对象 的特殊属性(多态) 借助构造函数完成
通过 Object.create 创建对象 语法:Object.create(proto, [propertiesObject]) proto:必须。表示新建对象的原型对象 ,即该参数会被赋值到目标对象(即新对象,或说是最后返回的对象)的原型上。该参数可以是 null、对象、函数的 prototype 属性 可选。 添加到新创建对象的可枚举属性(即其自身的属性,而不是原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应 Object.defineProperties 的第二个参数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 var object = Object .create(null ) var p1 = Object .create( { hair : 'black' , skin : 'yellow' }, { type: { value: 'person' , writable: false , enumerable: false , configurable: false , }, } ) p1.name = 'mcdowell' p1.age = '20' console .log(p1)
与 new Object 创建方式不同;new Object 创建的对象 原型 指向的原型对象一直都存在 Object.create(null) 创建的对象 为真正意义上的空对象,原型 为 undefined Object.create 直接以 传入对象 作为 原型 进行创建的 Object.create 创建的对象 的 constructor 与 new Object 创建的对象 的 constructor 都指向 Object 构造函数
通过 class 创建对象 类 不会像函数一样 去进行变量提升
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class Person { type = 'human' #study = 'true' constructor (name, age) { this .name = name this .age = age } static description = 'person' static create(name, age) { var person = new Person(name, age) console .log('创建了一个人' , person) return person } sayName() { console .log('说出自己的名字:' , this .name) } speak() { console.log('介绍自己:', this, '私有属性 #study', this.#study) } } console .log('输出静态属性description:' , Person.description)var p1 = Person.create('mcdowell' , 20 )p1.sayName() p1.speak()
extends 继承1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Man extends Person { constructor (...props) { super (...props) this .sex = 'man' } sayName() { console .log('我叫' , this .name, '我是个男的' ) } } var man = new Man('bart' , 22 )man.sayName() man.speak()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function Animal ( ) { this .name = name } Animal.prototype.speak = function ( ) { console .log(this .name + ' 发出声音' ) } class Dog extends Animal { speak() { super .speak() console .log(this .name + ' 汪汪叫' ) } } var dog = new Dog('阿福' )dog.speak()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 var Animal = { speak: function ( ) { console .log(this .name + ' 发出声音' ) }, } class Dog { constructor (name) { this .name = name } } Object .setPrototypeOf(Dog.prototype, Animal)var dog = new Dog('阿福' )dog.speak()
首先,我肯定是需要你告诉我,什么是面向对象,面向对象有哪些特点,以及这些特点的解释。 JavaScript 如何实现这些特点,比如封装、继承、多态。如果关于上述三点,你能够解释到有多少种实现方式、优缺点是什么。以及近几年流行的解决方案是什么。这就是加分 ,比如对于继承吧。类式继承、构造函数继承、组合继承、原型继承、寄生组合继承等等,说出大概的实现思路和优缺点,再介绍下 extends 或者 mixin 的实现甚至你可以衍生到 JavaScript 的模块化发展甚至到为什么现在 TS 如此流行。那么可以说到这一环节解答的就非常棒了。 回答完 JavaScript 的面向对象,是不是可以从此衍生下为什么需要面向对象。以及当先对于软件设计的高内聚、低耦合的思考?来个对此题一个提纲挈领的总结?