面向對象編程(OOP):
OOP-Object Oriented Programring:面向對象程序設計
POP-Procedure Oriented:面向過程程序設計
面向過程:C語言
面向對象:JS JAVA PHP C# (.net)Python Ruby go …
什麼是面向對象,要正確區分對象,類和實例:
對象: 萬物皆對象
類:對象的細分
實例:類中具體的事物
JS也是面向對象編程:類、實例
1 => Number
‘A’=> Srting
true => Boolean -都屬於大類Object
null => Null
undefined => Undefined
[] => Array
/^$/ => RegExp
function(){} => Function
{} => Object
每一個實例可以調用所屬類(整條鏈)中的屬性和方法。
所以學習JS時,按照面向對象的思維去考慮事情。
在開發中,遇到實例,要可以研究它的子類,父類,基類。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>面向對象</title>
</head>
<body>
<!--
每一個元素標籤(元素對象)都有一個自己所屬的大類。
div -> HTMLDivElement -> HTMLElement -> Element -> Node -> EventTarget -> Object
每一個實例可以調用所屬類(整條鏈)中的屬性和方法
子類不屬於父類的實例,實例是具體的東西,所以在學習JS時,要按照面向對象的思維去考慮事情
-->
<!-- 打開頁面,在控制檯輸入dir(box) => 可以看到它的類__proto__: HTMLDivElement -> __proto__: HTMLElement -> __proto__: Element -> __proto__: Node(元素節點) -> __proto__: EventTarget(事件目標類)-> __proto__: Object -->
<div id="box"></div>
<script>
/*
* JS中已經有一些內置的類,但在開發中,只有這一些是不夠的,所以會需要自定義類。
* => 創建一個函數(Function類的實例),直接執行就是普通函數,但是“new執行”,它則被稱爲一個自定義的類
* NEW函數執行:
* 形成一個全新的執行上下文EC
* 形成一個變量對象AO
* ARGUMENTS
* 形參賦值
* // 聲明其THIS指向(普通函數執行,new出來的實例指向不同)
* 初始化作用域鏈
* 【新】默認創建一個對象,而這個對象就是當前類的實例
* 【新】聲明其THIS指向,讓其指向這個新創建的實例
* 代碼執行
* 【新】不論其是否寫RETURN,都會把新創建的實例返回(特殊點)
*
*/
// new函數執行,既包含了普通函數應該辦的事,也包含了new時所有的特殊的處理
/*
function func() {
// let obj = {}; //=> 這個對象就是實例對象
//this -> obj
let x = 100;
this.num = x + 100; //=> 相當於給創建的實例對象新增一個num的屬性
//obj.num = 200; (因爲具備普通函數執行的一面,所以只有this.XXX=xxx才和創建的實例有關係,此案例中的x只是AO中的私有變量)
//return obj; 用戶自己返回內容,如果返回的是一個引用類型值,則會把默認返回的實例給覆蓋掉(此時返回的值就不再是類的實例了)。比如return {x:3000},輸出的就是x:3000,基本類型的值沒有影響。
}
let f = new func();
console.log(f); //=> f是func這個類的實例
// let f2 = new func();
// console.log(f2);
// console.log(f === f2); //false =>因爲每一次new出來的都是一個新的實例對象,(一個新的堆內存),所以是不相等的
// func(); //=> this:window 變量對象AO(FUNC): {x:100} ...普通函數執行
console.log(f instanceof func);//TRUE ;instanceof 用來檢測某一個實例是否屬於這個類 在此即代表f是否是func的實例
*/
</script>
<script>
function Dog(name) {
this.name = name;
}
Dog.prototype.bark = function () {
console.log('wangwang');
}
Dog.prototype.sayName = function () {
console.log('my name is' + this.name);
}
/*
使用new可以實現
let sanmao = new Dog('三毛');
sanmao.sayName();
sanmao.bark();
*/
/*
*內置NEW的實現原理
* @params:
* Func:操作的那個類
* ARGS:NEW類的時候傳遞的實參集合
* @return:
* 實例或者自己返回的對象
*/
function _new(Func, ...args) {
// =>在此是執行的過程
// 默認創建一個實例對象(而且是屬於當前這個類的一個實例)
// let obj = {};
// 若想要obj指向Dog的原型,需要以下代碼
// obj.__proto__ = Func.prototype; //=> IE大部分瀏覽器中不允許我們直接操作__proto__,所以可以直接將lei obj = {}和obj.__proto__ = Func.prorotype合併爲下邊的一步:
let obj = Object.create(Func.prototype);
// 也會把類當做普通函數執行
// 執行的時候要保證函數中的THIS指向創建的實例
let result = Func.call(obj, ...args);//當做普通函數執行,傳參數...args,要把this指向當前的實例,使用call轉換this
// 若客戶自己返回引用值,則以自己返回的爲主,否則返回創建的實例
if ((result != null && typeof result === "object") || (typeof result === "function")) {
return result
}
return obj;
}
let sanmao = _new(Dog, '三毛');
console.log(sanmao); //name: "三毛" 原型指向object __proto__: Object ,是沒有指向Dog.protoType的,sanmao.bark()會報錯,Uncaught TypeError: sanmao.bark is not a function,因爲原型沒有指對
/*
若使用new,在控制檯中輸入 sanmao = new Dog();原型指向Dog.prototype,結果是這樣的:sanmao= new Dog('三毛');
Dog {name: "三毛"}
name: "三毛"
__proto__: Object
bark: ƒ ()
sayName: ƒ ()
constructor: ƒ Dog(name)
__proto__: Object
*/
sanmao.bark(); //=>'wangwang'
sanmao.sayName();//=>"my name is 三毛"l
console.log(sanmao instanceof Dog); //=>true
</script>
</body>
</html>
內置NEW的實現原理
@params:
Func:操作的那個類
ARGS:NEW類的時候傳遞的實參集合
@return:
實例或者自己返回的對象
function new(Func, …args) {
// =>在此是執行的過程
// 默認創建一個實例對象(而且是屬於當前這個類的一個實例)
// let obj = {};
// 若想要obj指向Dog的原型,需要以下代碼
// obj.proto = Func.prototype; //=> IE大部分瀏覽器中不允許我們直接操作__proto_,所以可以直接將lei obj = {}和obj.proto = Func.prorotype合併爲下邊的一步:
//create方法,可見https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create
let obj = Object.create(Func.prototype);
// 也會把類當做普通函數執行
// 執行的時候要保證函數中的THIS指向創建的實例
let result = Func.call(obj, ...args);//當做普通函數執行,傳參數...args,要把this指向當前的實例,使用call轉換this
// 若客戶自己返回引用值,則以自己返回的爲主,否則返回創建的實例
if ((result != null && typeof result === "object") || (typeof result === "function")) {
return result
}
return obj;
}