



/*
1.编程语言常见的有两种,一种是基于类 一种是基于原型,基于类的代表java,原型的代表js
1.1.基于类 总是先划分类关注类直接关系,要现有类再去创建一个对象
1.2.基于原型,不会去显示定义一个类,而是会通过其他类实例添加属性和方法。也可以使用空对象直接创建
区别: 基于原型是在不定义class 的情况下依然能创建一个object,
相同:无论你是js 也好java也好本质都是面向对象,只是实现方式不同
学习的时候一直对js产生疑问:在学习其他语言后,在学习js很多人都有迷茫,这个迷茫的原因,
主要是历史原因,设计的时候模仿java导致引入了 'new ,this'一类的语言特性,让人忘记了
他是基于原型,他有他的优势,以至于总是去用基于类的角度去看
注:做一个心得,在java这类语言通过类创建好的对象,是不能再给对象添加属性和方法,相反js这类
基于原型的语言就可以做到,做个不恰当的比喻,java写一个老虎你给规定这个老虎是东北虎 继承猫科类
,js就是这个老虎跟猫很像就是叫的声音大小不一样,我随意把猫这个对象加点东西减点东西就变成了老虎。
可以理解成js更多的韵味在照猫画虎,站在两者本身设计上就是两种模式来理解,各有各的好处仅此而已
2.首先js 是原型创建对象的,使用原型到对象有两种方式
2.1. 第一种就复制一个对象,从此两个对象没有关系
2.2. 不是真的复制原型对象,只是使得对象 持有一个原型的引用
3.什么是对象
3.1.对象具有唯一标识性:即使完全相同的两个对象,也并非同一个对象。
3.2.对象有状态:对象具有状态,同一对象可能处于不同状态之下。
3.3.对象具有行为:即对象的状态,可能因为它的行为产生变迁。
注:大白话两个写法一样的对象不一定相等内存指向不同,行为状态就是属性和方法,js更喜欢把他们都叫属性
4.es6开始js的类写法和java这类很像,但是js一等公民就是function,class只是一个语法糖,而且
js 属性不是你单单看到的,一个属性使用一组特征来描述的属性 这就是' 数据属性/访问器属性'。
4.1.数据属性决定了js定义中对象属性的'值','能否被赋值','被枚举','能否被删除就是delete'
4.2.访问器属性 '读取属性时调用的函数','写入属性时调用的函数','被枚举','能否被删除就是delete'
原型模式
1.原型编程思想中,类并不是必须,对象也不是必须从类中创建
1.1.一个是并不真的去复制一个原型对象,而是使得新对象持有一个原型的引用;
1.2.另一个是切实地复制对象,从此两个对象再无关联。
2.js 没有类的概念,所谓的类的概念只是写法上和具有类的语言相似,
用mdn的话来说js是动态的并且本身也不提供class的实现
3.站在原型的角度来说如果A对象是从B对象克隆来的,那么B对象就是A对象的原型,js
中对象的原型都来自Object,但是js原型末端是null
4.js的继承是通过原型链实现的
4.1.所有数据都是对象,除了undefined
4.2.要得到一个对象不是通过实例化实现的,而是找到一个对象作为原型并且克隆
4.3.对象会记住他的原型
4.4.如果对象无法响应某个请求,他会把这个请求委托给自己原型
*/
function DoSomething(){}
console.log( DoSomething.prototype );
DoSomething.prototype.name = 'wang'
// {
// name: "wang", ------------> name 属性是DoSomething自己的所以不是从他的copy原型来的,因此不再__proto__
// constructor: ƒ DoSomething(),
// __proto__: { -----------------> 这里的原型链指向的是Object,这证明最开始说的'Object'就是所有对象的原型'
// constructor: ƒ Object(),
// hasOwnProperty: ƒ hasOwnProperty(),
// isPrototypeOf: ƒ isPrototypeOf(),
// propertyIsEnumerable: ƒ propertyIsEnumerable(),
// toLocaleString: ƒ toLocaleString(),
// toString: ƒ toString(),
// valueOf: ƒ valueOf()
// }
// }
const doSomething = new DoSomething()
doSomething.age = 17
console.log( doSomething)
// {
// age: 17, ---------》 age 属性是doSomething 的因此不再__proto__
// __proto__: { ---------》doSomething 是从DoSomething克隆来的因此一层原型链指向是DoSomething
// name: "wang",
// constructor: ƒ DoSomething(),
// __proto__: { -----------------》DoSomething 是从Object 来的因此第二层是在Object
// constructor: ƒ Object(),
// hasOwnProperty: ƒ hasOwnProperty(),
// isPrototypeOf: ƒ isPrototypeOf(),
// propertyIsEnumerable: ƒ propertyIsEnumerable(),
// toLocaleString: ƒ toLocaleString(),
// toString: ƒ toString(),
// valueOf: ƒ valueOf()
// }
// }
// }
/* -----------------------理解4.2---------------------------
1.当js时候我们通过new 去生成对象,在java这里语言中new 就是一个实例化的过程,
但js 是基于原型只是写法类似,但实际做的却大相近庭
2.所以要做的不是实例化而是找到一个对象作为原型来克隆它
*/
function Person( name ){
this.name = name;
};
Person.prototype.getName = function(){
return this.name;
};
var objectFactory = function(){
// 创建一个 空对象
var obj = new Object();
// 获取构造函数
var Constructor = [].shift.call( arguments )
// 改变当前obj 空对象原型链的指向
obj.__proto__ = Constructor.prototype
// 改变构造函数指向
var ret = Constructor.apply( obj, arguments );
return typeof ret === 'object' ? ret : obj; // 确保构造器总是会返回一个对象
}
// 这个写法等同 console.log(new Person('wang'))
var a = objectFactory( Person, 'sven' );
console.log(a)
console.log( a.name ); // 输出:sven
console.log( a.getName() ); // 输出:sven
console.log( Object.getPrototypeOf( a ) === Person.prototype );