<!--
Created by wangyang on 2019-05-16.
[email protected]
http://www.itwangyang.xyz
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<title>Title</title>
<meta name="description" content="">
<meta name="keywords" content="">
<!--所有的IE都起作用:-->
<!--[if IE]>
<link rel="stylesheet" type="text/css" href="all-ie-only.css/> <![endif]-->
</head>
<body>
<script>
/**
* 數據類型,----值類型:數字、字符串、布爾值、null、undefined
* 複雜數據類型:引用類型,對象:數組、函數、正則表達式、Date
*/
//變量沒有聲明過,--》如果獲取變量的值,是會產生語法錯誤的 console.log(a);
/**
* undefined場景:
* 1.一個變量聲明瞭,但是沒有賦值 var a; console.log(a);
* 2.一個變量聲明瞭,並且賦值了一個undefined的值,var b = undefined; console.log(b);
* 3.一個對象中,獲取某個不存在的屬性的值 var c ={};console.log(c.name);
*/
/**
* 面向對象:
* 對象是鍵值對的集合:對象是由屬性和方法構成的;
*/
/**
* 對象屬性的操作:
* 1. 第一種方式:.語法
* student.name
* 缺陷:後面不能使用js中的關鍵字、保留字(class/this/function/)
* 後面不能使用數字的
*
*
* 2. 第二種:使用更廣,推薦
* student["name"]; 等價於 student.name
*
*設置屬性:
* student ["gender"] = "男";
*
*
* 刪除屬性:
* delete student["gender"]
*
*/
//1.創建對象
const Person = {
gender: '男',
height: 185,
toShanghai: function () {
console.log('做🚄去上海');
}
};
//2.獲取屬性
console.log(Person.gender);
console.log(Person['height']);
//3.設置屬性
Person.address = "上海市閘北區";
Person.height = 180;
//4.刪除屬性
delete Person.gender;
delete Person.a;
//5.清空對象
Person = {}; //Person對象不再具有任何屬性
Person = null; //表示將Person變量的值賦爲null,從此以後person不再是一個對象了
</script>
</body>
</html>
1.構造函數
<!--
Created by wangyang on 2019-05-16.
[email protected]
http://www.itwangyang.xyz
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<title>Title</title>
<meta name="description" content="">
<meta name="keywords" content="">
<!--所有的IE都起作用:-->
<!--[if IE]>
<link rel="stylesheet" type="text/css" href="all-ie-only.css/> <![endif]-->
</head>
<body>
<script>
function Person(age, gender) {
this.age = age;
this.gender = gender;
//此時的內存依然浪費了---》原型
this.syaHello = function () {
}
}
//Person是p1的構造函數
let p1 = new Person(5, '女');
let p2 = new Person(51, '女');
let p3 = new Person(52, '女');
let p4 = new Person(15, '女');
let p5 = new Person(25, '女');
console.log(p1, p2, p3, p4, p5);
</script>
</body>
</html>
2.構造函數的返回值
<!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>Document</title>
</head>
<body>
</body>
<script>
//1、
function _fn(){
return 5;
}
var s=new _fn();
//s是_fn構造函數的實例
//2、
function _fn3(){}
var q1=new _fn3();
//q1是_fn3構造函數的實例
//3、
function fn3(){
return [1,3,5];
}
var qw=new fn3();//qw=[1,3,5]
console.log(qw);
//qw不是fn3構造函數的實例
//如何判斷一個數據是否是複雜數據類型?
//使用排除法:
//a、看它的值是不是:數字、字符串、布爾值、null、undefined,
//b、如果不是以上5種值,那就是複雜數據類型
// 舉例:
// [1,3,5]
// /abc/
// function(){}
// new Object();
//爲什麼要理解構造函數的返回值?
//String是一個內置函數
//a、String()
//b、new String()
//結論:一個函數通過new調用,或者不通過new調用,很多時候會有截然不同的返回值
//我如何分辨出一個對象到底是不是某個構造函數的實例?
//a、var isTrue=xxx instanceof Person
function Person(){
}
var p1=new Person();
console.log(p1 instanceof Person);//true,就是Person的實例
function Student(){
return 100;
}
var s1=new Student();
console.log(s1 instanceof Student);//true,就是Student的實例
function Programmer(){
return [1,3,5]
}
var pro=new Programmer();//pro並不是Programmer的實例
console.log(pro instanceof Programmer);//false
console.log("是數組的實例嗎?",pro instanceof Array);//true
//小技巧:如何通過肉眼識別xxx對象時哪個構造函數的實例?
//xxx.__proto__屬性,也是對象,該對象中一般都會有一個constructor屬性,這個只想PPP函數,那麼就可以認爲:xxx是PPP構造函數的實例
//typeof運算符,只能判斷:數字、字符串、布爾值、undefined、函數
//切記:千萬不能使用typeof運算符來判斷對象的構造函數
//typeof null === "object"
//typeof {} === "object"
//typeof [] === "object"
//typeof function(){} === "function"
//typeof /abc/ === "object"
</script>
</html>
3.爲什麼要繼承?
<!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>Document</title>
</head>
<body>
</body>
<script>
function Person(name,age){
this.name=name;
this.age=age;
this.say=function(){}
}
var p1=new Person();
var p2=new Person();
//p1對象和p2對象的say方法是否是同一個方法:false
console.log(p1.say===p2.say);
//由於say方法可能功能相似,但是不是同一個方法(沒有指向同一塊內存,會造成內存浪費)
//解決方案:把say方法寫在他們共同的(父對象)中
//其實他們共同的父對象,就可以通過:Person.prototype來獲取
//-->只要把say方法寫在Person.prototype中,那麼say方法就是同一個方法
Person.prototype.run=function(){
console.log('時速500KM');
}
//此時p1和p2都可以訪問到run方法
p1.run();
p2.run();
//驗證p1.run和p2.run是否是同一個方法?
console.log(p1.run == p2.run); //指向同一個方法,這種方法避免了內存的浪費
console.log(p1.run == Person.prototype.run);
//true
var p3=new Person();
console.log(p3.run == p1.run); //true
console.log(p3.run === p1.run);//true
//結論:只要往某個構造函數的prototype對象中添加某個屬性、方法,那麼這樣的屬性、方法都可以被所有的構造函數的實例所共享
//==>這裏的【構造函數的prototype對象】稱之爲原型對象
// Person.prototype是 p1 p2 p3 的原型對象
// Person.prototype是Person構造函數的【實例】的原型對象
//猜猜看?
// Person的原型對象是誰呢?
// -->首先要知道Person的構造函數:-->Function
// -->所以Person的原型對象是:Function.prototype
// p1的原型對象是誰呢?
// -->首先要知道p1是誰創建的? -->Person
// -->所以p1的原型對象時: Person.prototype
</script>
</html>
4.繼承
<!--
Created by wangyang on 2019-05-17.
[email protected]
http://www.itwangyang.xyz
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<title>Title</title>
<meta name="description" content="">
<meta name="keywords" content="">
<!--所有的IE都起作用:-->
<!--[if IE]> <link rel="stylesheet" type="text/css" href="all-ie-only.css/> <![endif]-->
</head>
<body>
<script>
function Person(name,age) {
this.name = name;
this.age = age;
this.sayHello = function () {
};
}
let p1 = new Person();
let p2 = new Person();
console.log(p1.sayHello === p2.sayHello);//false
//沒有指向同一塊內存,會造成內存浪費;解決方案:吧sayHello寫在他們共同的(父對象)中
//其實他們共同的父對象,就可以通過Person.prototype來獲取,就可以指向同一塊內存中
Person.prototype.run = function () {
console.log('hha');
};
p1.run();
p2.run();
console.log(p1.run === p2.run);//true
//結論:只要往某個構造函數的prototype對象中添加某個屬性,方法,那麼這樣的屬性,方法都可以被所有的構造函數的實例所共享
//----》在這裏,【構造函數的prototype對象】稱爲原型對象
/**
* Person的原型對象是誰?
* ---》手寫要知道Person的構造函數:-----》Function
* --->所有Person的原型對象是:Function.prototype
*
*/
//繼承第一種方式
function Tiger() {
}
Tiger.prototype = {
sayHello:function () {
},
eat:function () {
}
};
let tiger = new Tiger();
console.log(tiger.sayHello);
console.log(tiger.eat);
//缺點:添加1,2個無所謂,但是如果太多了,內存浪費
//繼承的第一種方式:原型鏈繼承1
/**
* Person.prototype.say=function(){
* console.log("你好")
* }
缺點:添加1、2個方法無所謂,但是如果方法很多會導致過多的代碼冗餘
// 繼承的第二種方式:原型鏈繼承2
Person.prototype={
constructor:Person,
say:function(){
console.log("你好");
},
run:function(){
console.log("正在進行百米衝刺");
}
}
注意點:
a、一般情況下,應該先改變原型對象,再創建對象
b、一般情況下,對於新原型,會添加一個constructor屬性,從而不破壞原有的原型對象的結構
//繼承的第三種方式:拷貝繼承(混入繼承)
場景:有時候想使用某個對象中的屬性,但是又不能直接修改它,於是就可以創建一個該對象的拷貝
實現1: js var source={name:"李白",age:15} var target={}; target.name=source.name target.age=source.age;
上面的方式很明顯無法重用,實際代碼編寫過程中,很多時候都會使用拷貝繼承的方式,所以爲了重用,可以編寫一個函數把他們封裝起來: js function extend(target,source){ for(key in source){ target[key]=source[key]; } return target; } extend(target,source)
由於拷貝繼承在實際開發中使用場景非常多,所以很多庫都對此有了實現
jquery:$.extend
es6中有了對象擴展運算符彷彿就是專門爲了拷貝繼承而生: js var source={name:"李白",age:15} var target={ ...source }
//繼承的第四種方式:原型式繼承
場景:
創建一個純潔的對象
創建一個繼承自某個父對象的子對象
使用方式:
- 空對象:Object.create(null)
var o1={ say:function(){} }
var o2=Object.create(o1);
繼承的第五種方式:借用構造函數實現繼承
場景:適用於2種構造函數之間邏輯有相似的情況
function Animal(name){ this.name=name; } function Person(name,age){ this.name=name; this.age=age; }
以上代碼用借用構造函數實現 js function Animal(name,age){ this.name=name; this.age=age; } function Person(name,age,address){ Animal.call(this,name); //this.name=name; //this.age=age; this.address=address; }
*
*/
</script>
</body>
</html>