1. Object
new Object()
缺点
使用同一个接口创建很多对象,产生大量代码
2.字面量
var a= {b:c}
缺点
使用同一个接口创建很多对象,产生大量代码
3.工厂模式
原理
发明一种函数 封装特定接口 返回一个对象
优点
解决代码重复
缺点
无法解决对象识别的问题
function createPerson (name,age){
var o = new Object();
o.name = name ;
o.age= age;
o.sayName = function(){
alert(this.name);
}
return o;
}
//多次调用 返回一个对象 无法识别这个对象是谁创建的
var person1 = createPerson('ss',10);
4.构造函数模式
原理
构造函数可以用来创建特定类型的对象
优点
特性 可以通过constructor 标识对象类型
缺点
构造函数中包含方法时 每生成一个新的对象 这个对象中就包含一个新的同名的方法(浪费内存) 实际上没有必要在 执行代码前就把 完成相同任务的方法 绑定在特定对象上
function Person (name,age){
this.name = name ;
this.age= age;
this.sayName = function(){
alert(this.name);
}
}
var person1 = new Person('ss',10);
// 方法没有公用
//与工厂模式不同
1. 没有显示的创建对象
2. 直接将属性和方法赋值给 this 对象
3. 没有return 语句
new
操作符的运行过程
- 创建一个新对象
- 将构造函数的作用域赋给新对象 (因此 this 指向这个对象)
- 执行构造函数代码
- 返回新对象
简单实现一个new
// 调用构造函数
function create(Con, ...args) {
//创建对象
let obj = {}
// 构造函数的原型 创建的对象进行原型关联 即为 对象的 __proto__ 属性 指向原型对象
// obj.__proto__ = Con.prototype;
Object.setPrototypeOf(obj, Con.prototype)
// 运行函数
let result = Con.apply(obj, args)
// 返回对象
return result instanceof Object ? result : obj
}
constructor(构造函数属性)
: 用来标识对象类型
instanceof
操作符 instanceof
并不关心构造函数,它真正关心的是原型链。
function B(){};
var A = new B();
console.log(A instanceof B);
沿着A的proto这条线来找,同时沿着B的prototype这条线来找,如果两条线能找到同一个引用,即同一个对象,那么就返回true。如果找到终点还未重合,则返回false。
构造函数
只要使用new 操作符 调用的就是构造函数 不使用它调用的时候 就是普通函数
5.原型模式
原理
每个函数都有一个prototype 的属性 , 此属性是一个指针,指向一个对象(包含特定类型的所有实例共享的属性和方法) 指向的对象 可以说是 实例的原型对象
优点
共享所有原型对象包含的属性和方法
缺点
原型中所有属性都是被很多实例所共享的, 但是基本类型的属性没有问题 但是所有实例同名引用属性的值都会指向一个地方
//
function Person () {
Person.prototype.name = "p1";
Person.prototype.age = 10;
Person.prototype.sex = "female";
Person.prototype.sayName =function(){
console.log(this.name);
}
}
/*
function Person () {
}
Person.prototype.name = "p1";
Person.prototype.age = 10;
Person.prototype.sex = "female";
Person.prototype.sayName =function(){
console.log(this.name);
}
------
function Person () {
}
// 重写 没有construtor
Person.prototype= {
//construtor:
name : "p1",
age : 10,
sex : "female",
sayName : function(){
console.log(this.name);
}
}
*/
var per1 =new Person();
var per2 =new Person();
console.log(Person.prototype);
Person.prototype.isPrototyeOf(per1)
Person.prototype.isPrototyeOf(per2)
原型对象
- 任何时候只要创建新函数,就会为该函数创建一个
prototype
属性,此属性指向原型对象 - 所有原型对象自动获得一个
construtor
构造函数属性 其他方式 的这个值有嘛
isPrototypeOf
确定对象之间是否存在
getPrototypeOf
获取对象的_ proto _ 属性的值
原型链查找
从对象实例本身开始--原型对象
同名属性
不能被覆盖只能被屏蔽
hasOwnProperty
检测属性在原型中还是当前实例中
in
只要能访问就返回true
5.组合使用构造函数和原型模式
此为最常见方法
原理
- 使用构造函数 定义实例专有属性
- 使用原型模式定义方法和共享属性
缺点
独立的构造函数和原型 不利于代码的可读性
function Person(name, age, job){
this.name = name;
this.age = age;
this.job = job;
this.friends = ['aa', 'bb'];
}
Person.prototype = {
constructor:Person,
SayName : function(){
alert(this.name);
}
}
var person1 = new Person("zhangsan", 29, "Software Enginner");
var person2 = new Person("lisi", 31, "Doctor");
person1.friends.push('cc');
alert(person1.friends); //aa, bb, cc
alert(person2.friends); // aa, bb
alert(person1.friends === person2.friends); //false
alert(person1.sayName === person2.sayName); //true
6.动态原型模式
原理
通过构造函数初始化原型 有点像单例模式
缺点
独立的构造函数和原型 不利于代码的可读性
function Person (name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
//
if(typeof this.sayName != "function"){
Person.prototype.sayName = function(){
console.log(this.name);
}
Person.prototype.sayAge = function(){
console.log(this.age);
}
}
}
var per = new Person("la", 19, "man");
7. 寄生构造函数模式
在前几种模式不适用的情况下 使用该模式
在特殊情况下为对象创建构造函数 ?
原理
创建一个函数,分装创建对象的代码,返回新对象 长得和工厂模式一模一样
8. 稳妥构造函数
没有公共属性,安全模式中使用 ,不适用this
9.es6 class
一种定义构造函数及其原型方法的语法糖
class MyClass {
// class 方法
constructor() { ... }
method1() { ... }
method2() { ... }
method3() { ... }
...
}
class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// 类是函数
alert(typeof User); // function
// ...或者,更确切地说是构造方法
alert(User === User.prototype.constructor); // true
// User.prototype 中的方法,比如:
alert(User.prototype.sayHi); // alert(this.name);
// 实际上在原型中有两个方法
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi
// 测试枚举
for(var a in u ){console.log(a)}
Es5 实现
// 以纯函数的重写 User 类
// 1. 创建构造器函数
function User(name) {
this.name = name;
}
// 任何函数原型默认具有构造器属性,
// 所以,我们不需要创建它
// 2. 向原型中添加方法
User.prototype.sayHi = function() {
alert(this.name);
};
// 使用方法:
let user = new User("John");
user.sayHi();
// 访问器属性 es6
class User {
constructor(name) {
// 调用 setter
this.name = name;
}
get name() {
return this._name;
}
set name(value) {
if (value.length < 4) {
alert("Name is too short.");
return;
}
this._name = value;
}
}
let user = new User("John");
alert(user.name); // John
es5
Object.defineProperties(User.prototype, {
name: {
get() {
return this._name
},
set(name) {
// ...
}
}
});
区别
- 内部去呗
- 类方法不可枚举
- 类默认使用 use strict 在类构造函数中的所有方法自动使用严格模式。
- 可以直接写 访问器属性
学习整理
JS高程学习-第六章(一)---认识对象
JS高程学习-第六章(二)---创建对象
JS高程学习-第六章(三)---对象继承