## 1.繼承的實現方式
### 1. 混入式繼承(for in)
<script>
<script>
//當前沒有的屬性和方法,別人有,拿過來用 ,就是繼承
var o = {
}
var obj = {
name :"張三",
age : 18,
sayHello :function () {
console.log("Hello world");
}
}
//混入式繼承
for(var k in obj){
o[k] = obj[k];
}
console.log(o);
</script>
### 2.經典繼承
<script>
//《JavaScript語言精粹》做者提出了一個方式來實現繼承
// function jicheng(obj){
// var o = {};
// o.__proto__ = obj;
// return o;
// }
//
// var o = jicheng({name:"張三"});
// console.log(o);
//經典繼承的語法
//Object.create(obj)
//返回值爲一個對象,繼承自參數中的obj
//這個方法是ES5中出來的,因此存在兼容性問題
// var o = {
// name:"週三"
// };
// var obj = Object.create(o);
//
// console.log(obj.name);
//如何處理Object.create的兼容性問題
var obj = {
name:"週三"
};
//檢測瀏覽器的能力,若是沒有Object.create方法就給他添加一個(不推薦使用)
if(Object.create){
var o = Object.create(obj);
}else{
Object.create = function () {
function F() {
}
F.prototype = obj;
var o = new F();
}
var o = Object.create(obj);
}
//本身定義個函數
function create(obj){
if(Object.create){
return Object.create(obj);
}else{
function F() {
}
F.prototype = obj;
return new F();
}
}
</script>
### 3.原型繼承
<script>
//原型繼承
//利用原型中的成員能夠被和其相關的對象共享這一特性,能夠實現繼承
//這種實現繼承的方式,就叫作原型繼承
//1.給原型對象中添加成員(經過對象的動態特性) 不是嚴格意義上的繼承
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function () {
console.log("我想死你了");
}
var p = new Person("馮鞏",50);
p.sayHello();
//這裏的p對象就繼承原型
//2.直接替換原型對象
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayHi = function () {
console.log("Hey man");
}
var parent = {
sayHello : function () {
console.log("我想你死了");
}
}
Person.prototype = parent;
var p = new Person("馮鞏",50);
p.sayHello();
p.sayHi(); 替換以後,sayHi方法不復存在
//p對象繼承了原型對象(parent對象)
//注意:使用替換原型的方式實現繼承的時候,原有原型中的成員就會丟失
//3.利用混入的方式給原型對象添加成員
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayHi = function () {
console.log("Hey man");
}
var parent = {
sayHello : function () {
console.log("我想你死了");
}
}
for(var k in parent){
Person.prototype[k] = parent[k];
}
var p = new Person("馮鞏",50);
p.sayHello();
//也是實現了繼承 p繼承自原型對象
</script>
### 4.繼承的應用
<script>
var arr = [1, 2, 3];
//開發人員A想要的sayHello
Array.prototype.sayHello =function () {
console.log("來呀,互相傷害啊");
}
//開發人員B想要的sayHello
Array.prototype.sayHello =function () {
console.log("我是一個數組,很高興認識你,呵呵")
}
//若是直接修改內置對象的原型,會影響整個開發團隊
arr.sayHello();
//擴展內置對象(就是給內置對象新增成員)
//var str = "+++abc+++";
//console.log(str.trim("+"));
//做業:擴展String內置對象,強化trim功能
//如何安全的擴展一個內置對象
function MyArray() {
//我本身的屬性
this.name = "我是一個數組";
this.sayHello = function () {
console.log("個人sayHello方法");
}
}
var arr = new Array();
//繼承以後,個人數組中就有了原生數組對象的全部的屬性和方法
MyArray.prototype = arr;
MyArray.prototype.safdaf =function () {
}
//myArr這個對象就繼承自arr
var myArr = new MyArray();
myArr.push(100);
myArr.push(2,3,4,5)
console.log(myArr);
var arr = new Array();
function BdeArray(){
this.sayhello=function () {
}
}
BdeArray.prototype = [];
var arr = new BdeArray();
var arr = new MyArray();
</script>
## 2.原型鏈
### 1.原型鏈結構概述
<script>
//1.什麼是原型鏈?
//每一個構造函數都有原型對象
//每一個對象都會有構造函數
//每一個構造函數的原型都是一個對象
//那麼這個原型對象也會有構造函數
//那麼這個原型對象的構造函數也會有原型對象
//這樣就會造成一個鏈式的結構,稱爲原型鏈
//2.原型鏈結構的基本形式
function Person(name){
this.name = name;
}
var p = new Person();
//p ---> Person.prototype --->Object.prototype---->null
//屬性搜索原則:
//1.當訪問一個對象的成員的時候,會如今自身找有沒有,若是找到直接使用,
//2.若是沒有找到,則去當前對象的原型對象中去查找,若是找到了直接使用,
//3.若是沒有找到,繼續找原型對象的原型對象,若是找到了,直接使用
//4.若是沒有找到,則繼續向上查找,直到Object.prototype,若是仍是沒有,就報錯
//原型繼承概念
//經過修改原型鏈結構實現的繼承,就叫作原型繼承
</script>
## 3.Object.prototype的成員
<script>
//1.constructor
//原型對象內的一個屬性,指向該原型對象相關聯的構造函數
//2.hasOwnProperty
//一個方法,用來判斷對象自己(不包含原型)是否擁有某個屬性
function Person(){
this.name = "王九"
}
Person.prototype.name = "張三";
var p = new Person();
console.log(p.name);
console.log(p.hasOwnProperty("__proto__"));
//3.propertyIsEnumerable
// 1. 判斷屬性是否屬於對象自己
// 2. 判斷屬性是否能夠被遍歷
console.log(p.propertyIsEnumerable("name"));
//Object.defineProperty();
// 使用以上方法添加屬性的時候,能夠附加一些信息,
// 例如這個屬性是否可寫 可讀 可遍歷
for(var k in p){
console.log(k);
}
//4. toString 和 toLocaleString
var o = {};
console.log(o.toString());
console.log(o.toLocaleString());
var now = new Date();
console.log(now.toString());
console.log(now.toLocaleString());
//5.valueOf
//獲取當前對象的值
function Person(){
}
var p = new Person();
//在對象參與運算的時候
//1.默認的會先去調用對象的valueOf方法,
//2.若是valueOf獲取到的值,沒法進行運算 ,就去去調用p的toString方法 最終作的就是字符串拼接的工做
console.log( 1 + p);
//6. __proto__
//原型對象對象中的屬性
//可使用 對象.__proto__ 去訪問原型對象
</script>
- constructor :指向和該原型相關的構造函數
- hasOwnProperty 方法: 判斷對象自己是否擁有某個屬性
- properIsEnumerable 方法: 1.判斷屬性是否屬於對象自己,2.判斷屬性是否能夠被遍歷
- toString toLocaleString: 將對象轉換成字符串 toLocalString轉換成字符串的時候應用的本地的設置格式
- valueOf 方法:在對象參與運算的時候,首先調用valueOf方法獲取對象的值,若是該值沒法參與運算,將會調用toString方法
- __proto__ 屬性: 指向當前對象的原型對象
## 4.建立函數的幾種方式
<script>
//1.直接聲明函數
function funcName(/*參數列表*/){
//函數體
}
//2.函數表達式
var funcName = function(){
};
//3.new Function
var func = new Function();
</script>
### 1.Function的使用
<script>
function Person(name, age){
this.name = name;
this.age = age;
}
var p = new Person("張三",19);
// var func = new Function("console.log('我是動態建立的函數');console.log(1);");
// func();
//Function這構造函數 能夠用來新建函數對象
//語法:
//0.一個參數都不傳的狀況 建立的就是一個空的函數
//var 函數名 = new Function()
//1.只傳一個參數的狀況 這個參數就是函數體
//var 函數名 = new Function("函數體")
//2.傳多個參數的狀況,最後一個參數爲函數體,前面的參數都是該函數的形參名
//練習:使用Function建立一個打印4句歌詞的函數
// var func = new Function("console.log('4句歌詞');");
// func();
//舉個栗子
//建立一個計算兩個數的和的函數
// var sum = new Function("a", "b", "return a + b;");
// console.log(sum(1, 1111));
// 練習: 利用 Function 建立一個求三個數中最大數的函數.
// var max = new Function("a", "b", "c", "return (a > b ? a : b)> c ? (a > b? a : b):c;");
// console.log(max(34, 45, 11));
//練習:傳入一個數組,求這個數組中的最大數
// var max = new Function("arr",
// "var maxNum = arr[0];" +
// "for(var i = 1;i<arr.length;i++){" +
// "if(maxNum < arr[i]){" +
// "maxNum = arr[i];" +
// "}" +
// "}" +
// "return maxNum;"
// )
//
// console.log(max([1, 2, 3, 44, 5, 6]));
window.onload =function () {
var script = document.getElementById("funcContent");
var str = script.innerHTML;
var max = new Function("arr", str);
console.log(max([1, 2, 3, 44, 5, 6]));
}
//如何解決使用Funciton建立函數時,代碼過長的問題
//1.可使用字符串拼接 讓代碼換行
//2.使用模板的方式,將代碼寫在模板標籤內(模板引擎),獲取該標籤的內容
//3.使用反引號(`) 引住字符串,那麼就能夠 換行了
var str = `adfafdsa
asdfas`;
console.log(str);
// 利用 Function 建立一個函數,
// 要求容許函數調用時傳入任意個數參數,
// 而且函數返回這些數字中最大的數字.
// function test(){
//
// }
//
// test(1,234,4);
</script>
<script type="text/template" id="funcContent">
var maxNum = arr[0];
for(var i = 1; i<arr.length; i++){
if(maxNum < arr[i]){
maxNum = arr[i];
}
}
return maxNum;
</script>
#### 1.1 模板引擎的代碼塊書寫例子
<script type="text/template" id="funcContent">
var maxNum = arr[0];
for(var i = 1; i<arr.length; i++){
if(maxNum < arr[i]){
maxNum = arr[i];
}
}
return maxNum;
</script>
### 2.argument對象
<script>
// 要求容許函數調用時傳入任意個數參數,
// 而且函數返回這些數字中最大的數字.
//函數內部的一個對象 arguments
//當函數調用的時候,系統會將全部傳入的實參,依次存入這個數組對象
function max(){
// console.log(arguments);
var maxNum = arguments[0];
for (var i = 1; i < arguments.length; i++) {
maxNum = maxNum > arguments[i] ? maxNum :arguments[i];
}
return maxNum;
}
console.log(max(1, 2, 34, 5, 6));
//練習,使用Function建立一個函數,
//給函數傳入任意個數的參數,
//在函數內進行去重操做,而後返回去重後的數組
var distinct = new Function(`
var arr = [];
for (var i = 0; i < arguments.length; i++) {
if(arr.indexOf(arguments[i])==-1){
arr.push(arguments[i]);
}
}
return arr;
`);
// console.log(distinct(1, 2, 34, 34, 5, 5));
function test(a, b){
console.log(a , b);
console.log(arguments);
}
test();
//1.一個函數有形參的時候,調用的時候,能夠不傳參數
//2.一個函數沒有形參的時候,調用時後,能夠傳參 arguments對象
//3.一個函數無論有沒有形參,調用的時候都會把實參的值存入arguments對象
4.arguments
//函數內部的一個對象,在函數調用的時候,默認的會將全部傳入的實參依次存入該對象
//是一個僞數組
//arguments.length 能夠用來表示傳入實參的個數
//arguments.callee 指向函數自己
</script>
### 3.eval函數
<script>
//eval函數能夠用來將字符串轉換成JavaScript代碼而且運行
var str = "var a = 10";
eval(str);
console.log(a);
//JSON格式的數據 JSON對象有兼容性問題
var jsonData = '({"name":"zs", "age":18})';
var o = JSON.parse(jsonData);
console.log(o);
eval("var o = "+ jsonData);
var o = eval(jsonData);
console.log(o);
//使用eval來解析JSON格式字符串的時候,會將{}解析爲代碼塊,而不是對象的字面量
//1.在JSON格式的字符串前面拼接上 "var o ="
//2.把JSON格式的字符串使用()括起來,就不會將{}解析爲代碼塊,而是表達式
var str = prompt("請輸入內容");
eval(str);
//不推薦使用eval
</script>
</head>
### 4.eval和Function的區別
1.Function和eval有什麼區別
//共同點,均可以將字符串轉換成js代碼
//不通點:
//1.Function 建立出來的是 函數 並不會直接調用,只有當手動去調用建立出來的函數的時候,才
會執行
//2.eval 把字符串轉成代碼以後,直接就執行了
2.Function 和 eval
1.Function 能夠用來建立函數 (Function能夠看作是一個構造函數,用來實例化函數對象)
// 語法 var fun = new Function();
建立函數的時候 若是使用的是 new Function(); 建立一個空函數
建立函數的時候 若是使用的是 new Fucntion(參數); 只有一個參數,那麼這個參數爲要建立的函數的函數
建立函數的時候 若是使用的是 new Funciton(參數1,參數2,...參數n) 那麼最後一個參數爲函數的函數體面的全部參數爲要建立的函數的形參名
//Function這個構造函數接收的全部的參數都是字符串類型的
2.eval 能夠將字符串轉換成js代碼而且執行
當使用eval解析 JSON格式的數據(字符串)的時候
會將字符串內的{}當作代碼塊來解析,因此直接解析 會報錯
解決方案:
1.在JSON格式的字符串前面拼接 "var 變量名 =" + JSON字符串
2.在JSON格式的字符串先後加上() "("+ JSON字符串 +")"
)
## 5.靜態成員和實例成員
<script>
function Person(){
this.name = "zs";
this.run = function () {
console.log("跑");
}
}
Person.prototype
console.log(Person.name);
var p = new Person();
//p.name
//靜態成員和實例成員的概念,是從其餘編程語言中引入的
//靜態成員:
//是指構造函數的屬性和方法
//實例成員:
//是指實例的屬性和方法
//__proto__
$("#id").css();
$("#id").text();
$.trim();
$.each();
$.extend();
//把工具方法,做爲靜態成員
//把跟對象相關的方法,做爲實例成員
</script>