一、對象定義的三種方式
一、對象的構成、
對象是由它本身和它的原型公共構成的, 對象的原型是 proto (也是一個對象)
二、原型鏈:
對象或構造函數(shù)由本身和原型構成,對象或構造函數(shù)也是一個對象,由本身和原型構成,這樣一直往后沿深,形成原型鏈。
二、定義對象鍵和鍵值
分為直接定義、追加定義
var obj2 = new Object();
// 添加對像內容
obj2.name = "張三";
obj2.age = 20;
console.log(obj2);
// 覆蓋定義 obj2對象
obj2 = {
height:"178cm",
hobby:function(){
console.log("喜歡籃球");
}
}
console.log(obj2);
三、對象和JSON之間的轉換
JSON鍵名一定要加 "",鍵值沒有函數(shù),規(guī)范 :引號使用--外單內雙
var JSON = '{"name":"張三","age":"19"}';
var json1 = JSON.stringify(obj2); // 對象轉json串(字符串化)
var newObj = JSON.parse(json1); // json數(shù)據(jù)轉換成對象(解析)
四、傳值和傳址問題
1、傳值,
var a = 10;
var b = a;
b = 5;
console.log(a,b); // 10 5 。不會相互影響
2、傳址
var obj1 = {
a:10
}
var obj2 = obj1;
obj2.a = 5;
console.log(obj1.a,obj2.a); // 5 5
// 數(shù)組傳址,數(shù)組之間相互影響
var arr1 = [1,2,3,4,5];
var arr2 = arr1;
arr2[1] = 10;
console.log(arr1[1]); // 10
解決傳址問題:
1、深拷貝 -- 將數(shù)組轉為JSON串,再轉為數(shù)組
var arr1 = [1,2,3,4,5];
var arr2 = JSON.parse(JSON.stringify(arr1));
arr2[1] = 10;
console.log(arr1); // 2
2、使用空的構造函數(shù),作為兩個函數(shù)原型的橋梁。
解決方案: 空的構造函數(shù),作為父級、子級的傳遞橋梁。
function People(sex,eat){
this.sex = sex;
this.eat = eat;
}
People.prototype.actions = () => {
console.log('People === actionsFn')
}
function Student(sex,eat){
this.sex = sex;
this.eat = eat;
}
Student.prototype.actions = () => {
console.log('Student === actions')
}
------------------------------
Student.prototype = People.prototype;
------------------------------
++++++++++++++++++++++++++++++
function Link(){
Link.prototype = People.prototype;
}
Student.prototype = new Link;
+++++++++++++++++++++++++++++++
Student.prototype.actions = () => {
console.log('Stundent === New');
}
const newPeo = new People('女','水果');
const newStu = new Student('man','dontknow');
newPeo.actions();
newStu.actions();
五、構造函數(shù)
構造函數(shù)(類似類的概念); 約定俗成:首字母大寫
1、定義構造函數(shù)
function People(eat,age){
this.eat = eat;
this.age = age;
this.action = function(){
console.log("吃飯,睡覺");
}
}
2、構造函數(shù)的原型
- 構造函數(shù)由本身和原型prototype構成;
- 原型鏈:原型是一個構造函數(shù),又由本身和構造函數(shù)構成,一直往后延深,形成原型鏈。
- 一般屬性寫在構造函數(shù)里,方法寫在原型上,目的是:便于維護
- 在寫方法時,直接:People.prototype = function({}),會覆蓋原有的原型
People.prototype.action = function(){
console.log(this); // 實列化是誰,this指向誰。
console.log(this.eat);
console.log("我是爸爸");
}
3、通過原型找構造函數(shù)
console.log(People.prototype.constructor);
4、調用構造函數(shù)
關鍵字 new:實列化構造函數(shù)。抽象具體化,將類變?yōu)閷ο?/p>
newPeople = new People("米飯",18);
console.log(newPeople.eat);
newPeople.action();
5、關鍵字new具體做的三件事:
創(chuàng)建空的對象
var newPeople = new Object();
將構造函數(shù)的this指向改變成空對象 (3種寫法:call/apply/bind)
People.call(newPeople,"米飯",18);
// People.apply(obj,["米飯",18])
// People.bind(obj)("米飯",18);
將構造函數(shù)的原型賦給對象原型
newPeople.__proto__ = People.prototype; // 構造函數(shù)的原型 賦給 實列化原型
6、構造函數(shù)的原型
console.log(People.prototype === newPeople.__proto__); // true , 只是表現(xiàn)形式不一樣
7、構造函數(shù)的 -- 繼承
1、改變this指向
function Father(eat,age){
this.eat = eat;
this.age = age;
this.fath = function(){
console.log("我是爸爸");
}
}
function Sons(eat,age){
Father.call(this,eat,age);
this.sonFn = function(){
console.log("我是兒子");
}
}
2、原型的繼承
// 不可以直接:Sons.prototype = father.prototype;
// -- 解決傳址問題 !!!
// 1、定義一個空構造函數(shù),其原型指向father原型,son原型指向其原型
function Center(){};
Center.prototype = Father.prototype;
Sons.prototype = new Center(); // 空構造函數(shù)只有原型
Father.prototype.typeFn = function(){
console.log("父級重寫");
}
Sons.prototype.typeFn = function(){
console.log("子級重寫");
}
var newSons = new Sons("蘋果",10);
var newFather = new Father("蘋果",10);
console.log(newSons.eat);
newSons.sonFn();
newSons.fath();
newFather.typeFn();
newSons.typeFn();
六、類的特性:封裝、繼承、多態(tài)、重載; [js:封裝、繼承]
1、封裝 -- 公有、私有屬性
function Person3(name){
// 1.1、私有屬性
var name = name;
// 1.2、公有屬性
this.height = "179cm";
// 1.3、get方法:通過公有方法,訪問私有屬性
this.get = function(){
return name;
}
// 1.4 set方法:設置私有屬性
this.set = function(newname){
name = newname;
console.log(name);
}
}
newPerson3 = new Person3("三三");
console.log(newPerson3.name); // undefind:作用域問題,訪問不到。只能在構造函數(shù)內部訪問
console.log(newPerson3.get()); // 三三
newPerson3.set("四四"); // 四四
2、繼承
1、利用 apply、call、bind 方法,改變this指向 實現(xiàn)繼承
- 通過 apply、call、bind:繼承父類 的 this ----> 只能繼承實例的 方法、對象
- 父類公有對象、方法 都通過 this 遞增,每 new 一個 實例都導致 this 內容的存儲,耗費很大內存
function Student(name, age, grade){
// 將 this 指向 Person,達到繼承 Person對象實例 的 方法、目的
Person.apply(this, arguments);
// Person.call(this, arguments);
// Person.bind(this)(arguments);
this.grade = grade;
}
function Person(name, age){
this.age = age;
this.name = name;
this.type = 'person';
}
Person.prototype.proFn = () => {
console.log('Person === proFn')
}
var student = new Student('sname', 'sage', 'sgrade');
console.log(student);
2、空對象作為中介
- 只能通過 Prototype 來傳遞
- 優(yōu)勢:
少 new 很多的 this 構造函數(shù),節(jié)省內存
子類 prototype 改變,不影響父類
function Student(name , age, grade){
this.grade = grade;
}
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.type = 'preson';
function Extend(Child, Partent){
var F = function(){}; // 空對象
F.prototype = Partent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child; // 將 Child 賦給 當前對象的構造函數(shù) ( 防止繼承鏈的紊亂,需手動把構造器指回Child )
Child.uber = Partent.prototype; // Child 的 Uber 屬性,直接指向 Partent 的 prototype (只是為了實現(xiàn)繼承的完備性,純屬備用性質)
}
Extend(Student, Person);
var student = new Student('sname', 'sage', 'sgrade');
Student.prototype.subType = 'ssubType';
console.log('student +++', student.type)
console.log('student +++', student.subType)
3、拷貝繼承
function Student(name, age, grade){
this.grade = grade;
}
function Person(name, age){
this.name = name;
this.age = age;
}
function Extend(Child, Partent){
var p = Partent.prototype;
var c = Child.prototype;
for (const i in p) { // 遍歷拷貝賦值
c[i] = p[i];
}
c.uber = p;
}
Person.prototype.type = 'person';
Extend(Student, Person);
Student.prototype.subType = 'sperson';
var student = new Student('sname', 'sage', 'sgrade');
console.log(student)
七、工廠模式
function Factory(height){
//obj人類
var obj = {};
obj.name = 20;
obj.name = "張三";
obj.height = height;
obj.hobby = function(){
console.log("我喜歡籃球");
}
return obj;
}
var newFactory = Factory("162");
console.log(newFactory.height);
newFactory.hobby();