天天看點

JavaScript學習筆記022-原型鍊0原型繼承0對象的深淺拷貝extends

Author:Mr.柳上原

  • 付出不亞于任何的努力
  • 願我們所有的努力,都不會被生活辜負
  • 不忘初心,方得始終

這幾天一直在做node項目實訓

學到了很多實際企業開發知識

學的東西

跟要運用起來的東西

就好像教會你1+1=2

然後讓你做高等代數

還需要加倍的努力啊

兄弟

<!DOCTYPE html> <!-- 文檔類型:标準html文檔 -->

<html lang='en'> <!-- html根标簽 翻譯文字:英文 -->

<head> <!-- 網頁頭部 -->

<meat charset='UTF-8'/> <!-- 網頁字元編碼 -->

<meat name='Keywords' content='關鍵詞1,關鍵詞2'/>

<meat name='Description' content='網站說明'/>

<meat name='Author' content='作者'/>

<title>前端59期學員作業</title> <!-- 網頁标題 -->

<link rel='stylesheet' type='text/css' href='css/css1.css'/> <!-- 外鍊樣式表 -->

<style type='text/css'> /*内部樣式表*/

</style>

</head>

<body> <!-- 網頁主幹:可視化區域 -->

<script>
/*
new:
生成一個對象
new執行的時候,函數内部的this指向這個new建立的對象
new執行的本次函數調用結束時,預設傳回這個new建立的對象
*/
function fn(){
this.name = name; 

// 函數内部生成的值,不是函數調用生成的,而是new生成的時候就有的特性
// this.name = arguments[0]; // 特性
}
fn.prototype = {
constructor = fn,
}
new fn();
// fn是構造函數
// fn.prototype是類的原型(給執行個體添加公有屬性)
// new fn()是類的執行個體化
// obj = new fn(),obj就是fn類的執行個體

/*
原型:prototype
原型的本質,是個json格式的對象
一個對象,是被這個對象對應的類所執行個體出來的
原型也是個對象
原型也是被它對應的類所執行個體出來的

數字,字元串,布爾,數組,函數,symbol
都有原型
Number,String,Boolean,Array,Function,Symbol
這些原型的原型
Object
js基于原型,Object是所有以上資料類型的原型,而原型是類執行個體出來的
Function(js最初的類,不同于上面的Function)
*/

// 原型鍊
// Objet的原型,是最頂層的原型
// 請求資料時,先向原型請求,沒有找到就繼續向原型的原型請求,直到最頂層Objet的原型,如果都沒有,就會抛出錯誤
// 原型也是一個對象,是以它也有對應的類的原型
// 一層一層的原型的鍊式關系,就是原型鍊

// hasOwnProperty 判斷一個屬性是否在原型上
obj.hasOwnProperty("name"); // true

// instanceof 判斷一個對象是否存在另一個對象的原型鍊上
obj instanceof fn; // true fn存在于obj的原型鍊上

// 原型繼承
// 私有屬性的繼承,是拷貝一個相似的
// 原型的繼承,是同一個
function Person(name){ // 類
this.name = name;

// 右邊指派交出的是對象的記憶體位址
// this.__proto__ === Person.prototype; // 原型倉庫
}

// 原型的繼承
Person.prototype = Array.prototype;  // 繼承數組的屬性
Person.prototype = String.prototype;  // 繼承字元串的屬性
......

Person.prototype.add = function (){} // 原型擴充方法
let p1 = new Person("fengyu"); // 執行個體

// 執行個體的__proto__指向了執行個體對應的類的prototype
console.log(p1.__proto__ === Person.prototype); // true

// 原型的指向:constructor
Person.prototype.constructor = Person;

// 使用對象的形式定義類
Person.prototype = {
constructor: Person, // 必須把指向加上
add (){}
}

// 最頂層對象原型的繼承
Object.prototype.fengyu = function (){
console.log(this); // this指向調用它的字元串
}
"123".fengyu(); // 最頂層對象原型的擴充方法,任何對象都能調用,不推薦使用

// 繼承
// 父類傳給子類
function P1(opt){ // 父類
this.name = opt.name;
this.age = opt.age;
}
P1.prototype.sayName = function (){
alert(this.name);
} 
function P2(opt){ // 子類,繼承父類
// P2的this指向改為P1
P1.call(this, opt); // 繼承私有屬性 基類

// 自行擴充屬性
this.sex = opt.sex;
}
// 繼承公有屬性
 // 方案一:P2的原型成為P1的原型(pass)
P2.prototype = P1.prototype; // 不推薦,引用型資料指派的是記憶體位址,擴充P2時會同時改變P1的環境
// 方案二:P2的原型成為P1的執行個體,P2的原型變成了P1原型的子類(pass)
P2.prototype  = new P1({}); // P1的原型上的私有屬性會出現異常值
// 方案三:新定義一個空的類,用新類的原型和P1交換(right)
function C(){}
C.prototype = P1.prototype;
P2.prototype = new C();
// 方案四:for in循環
for (var key in P1.prototype){
P2.prototype[key] = P1.prototype[key];
} // 不能克隆原型鍊,隻能在一層原型上生效

new P2({
name: "fengyu",
age: 18,
sex: "男",
})

// 對象的深淺拷貝
const obj = {
    a: 1,
    b: ["a", {
        b: 2,
        c: 3,
        d: [4, 5, 6]
    }]
}
function extend(ob1, deep){
    // deep判斷:true啟動深拷貝
    // deep判斷:false啟動淺拷貝
var obj = {};
    if(ob1 instanceof Array){
        obj = [];
    }
for (var key in ob1){
    var value = ob1[key];
    obj[key] = (!!deep && typeof value === "object" && value !== null) ? extend(value, deep) : value;
    }
    return obj;
}
// const obj2 = extend(obj); // 淺拷貝
const obj2 = extend(obj, true); // 深拷貝
obj2.b.push("c");
console.log(obj);
console.log(obj2);

// 騷的一匹的JSON拷貝(不支援函數)
const obj = {
    a: 1,
    b: ["a", {
        b: 2,
        c: [3],
        d: 4
    }]
}
const obj2 = JSON.parse(JSON.stringify(obj));
obj2.b[1].c.push("p");
console.log(obj);
console.log(obj2);
console.log(obj === obj2); // obj和obj2互不影響
// 縮進兩格
const json = JSON.stringify(obj, null, 2);
console.log(json);

// es6:繼承(extends)
class DogOne{
    constructor(name, age, sex, food, add, friend){
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.food = food;
        this.add = add;
        this.friend = friend;
    }
    eat(){
        console.log(this.name + "呼噜呼噜" + this.food);
    }
sport(){
        console.log(this.name + "嘿咻嘿咻" +this.add);
    }
}
class DogTwo extends DogOne{
    constructor(name, age, sex, food, add, friend){
// super必須調用,文法規定,本次調用super就相當于父類DogOne本身
// super不調用的時候,子類DogTwo 不具備this屬性
        super(name, age, sex, food, add, friend);
    }
sexS(){
        console.log(this.name + "噗哧噗哧" + this.friend);
        }
}
        
const dog1 = new DogOne("風嶼", 18, "女", "雞屁股", "窩", "小花");
const dog2 = new DogTwo("阿飛", 19, "男", "雞翅膀", "巢", "旺财");
dog1.eat();
dog1.sport();
// dog1.sex(); 
dog2.eat();
dog2.sport();
dog2.sexS();
console.log(dog1);
console.log(dog2);

</script>

</body>

</html>           

複制