js前端技術
一、前端技術
1、HTML
HTML(hypertext markup language)超文字標記語言,不同於程式語言。
超文字就是超出純文字的範疇,描述文字的顏色、大小、字型。
HTML由一個個標籤組成,標籤各司其職,有的提供網頁資訊,有的負責圖片,有的負責網頁佈局。
超文字需要顯示,就得有軟體呈現超文字定義的排版格式,,例如顯示圖片、表格、顯示字型的大小,顏色,軟體就是瀏覽器。
超文字的誕生是為了解決純文字不能格式顯示問題,是為了好看,但是隻用通過網路分享超文字的內容,所以制定了HTTP協議。
2、瀏覽器
1)歷史、1980年代,tim berners-Lee為cern設計基於超文字思想的enquire,以促進科研人員之間資訊更新和共享。19899年其編寫了《資訊化管理;建議》一文,並構建基於Internet的hypertext系統,並在cern開發了world wide web專案。打造了世界上第一站。於1991年8月6日上線。
Tim berners-lee於1990年發明了第一個瀏覽器,還發明瞭HTTP協議。
1994年MIT建立了w3c。w3c全球資訊網聯盟,負責全球資訊網持續發展,提出w3c的標準應該基於無專利權、無版稅。
Marc Andreessen於1993年發明了mosaic瀏覽器,看到了技術前景,不久後成立自己的公司---網景公司Netscape,1994發不了Netscape navigator瀏覽器,席捲全球。
1995年微軟釋出IE。
1999年網景被aol收購,收購後,Netscape公開了瀏覽器程式碼。建立了Mozilla組織。Mozilla組織使用gecko引擎重寫瀏覽器。。
2003網景被解散。
2008年google的Chrome瀏覽器待著v8引擎橫空出世。
2)網景公司
HTTP cookie,解決HTTP無狀態。
Javascript
Ssl協議:
Jar格式檔案,將Java的class檔案打包壓縮,並加上簽名。
2012年4月9日,微軟購買800項美國線上的專利或專利授權。
3)瀏覽器技術
瀏覽器是特殊的客戶端。
瀏覽器軟體分為兩個部分
外殼:
外殼提供使用者互動的介面。
核心(引擎engine)
提供HTML,css,影象的渲染引擎。提供DOM程式設計介面。
提供Javascript引擎。
排版(渲染)引擎 |
瀏覽器 |
說明 |
Gecko |
Firefox |
|
Trident |
IE,AOL |
|
Khtml |
|
|
Presto |
oPera |
|
Webkit |
Safari,Chrome |
|
Blink |
Chrome,Opera |
|
Js引擎:
Jscript、tracemonkey(firefox) v8等
使用jquery等框架來解決相容性問題。
3、js
是一種動態的弱型別的指令碼解釋性語言。和HTML、css秉承三大web核心技術。
4、ES
ECMAscript:是ecma國際組織
JavaScript是商品名。
2009年 ES5釋出
2015年ES6釋出
5、v8引擎
谷歌推出的,使用的是bsd協議開源。
二、nodejs
1、nodejs簡介
Nodejs是伺服器端執行JavaScript的開源、跨平臺執行環境。
作者是瑞安達爾(ryan dahl),2009年釋出,使用了v8引擎,採用時間驅動,非阻塞,非同步IO模型。
2012年,npm軟體包管理器誕生,通過其,可以方便的釋出,分享nodejs的庫和原始碼。
Nodejs4.0引入了ES6語言的特性。
2、安裝
國內阿里雲映象
https://npm.taobao.org/mirrors/node
Linux:
https://npm.taobao.org/mirrors/node/latest-v8.x/node-v8.11.3-linux-x64.tar.xz
windows:
https://npm.taobao.org/mirrors/node/latest-v8.x/node-v8.11.3-x64.msi
預設路徑安裝:
3、開發
Visual studio code
https://code.visualstudio.com/Download
4、註釋
和c、Java一樣
//單行註釋
/*comment*/ 多行註釋,在語句中間使用。
str = 'hello' + /*comment*/ 'student'
5、常量和變數
識別符號
識別符號必須是字母、下劃線、美元符號和數字,但必須是字母、下劃線、美元符號開頭。,不能是數字開頭。
識別符號區分大小寫。
宣告
var a宣告 a值為undefined 宣告全域性變數
let b 宣告 let 塊變數,區域性變數。
const c常量宣告時候必須賦值。後期不允許更改。明確知道一個識別符號定以後不在膝蓋,宣告的時候使用const常量,減少被修改的風險。
能給常量就不用變數。
變數和常量宣告和初始化的過程中是可以分開的。
var a
let b
console.log(a,b)
a = 1
b = 'a string'
console.log(a,b)
//const c //不能定義,因為const定義時候必須賦值,之後不可以再次進行更改
const c = 100
console.log(c)
var y //只是複製,y的值為undefined
var x = 1 //規範的宣告並初始化,宣告全域性或區域性變數
function hello()
{
var a //只是宣告,a為undefined,作用域是在函式中
a = 100 //賦值
}
//console.log(2,a) //丟擲錯誤,變數a未定義
//a = 200 //不能提升作用域
//var a = 200;hello(); //var提升作用域
//console.log(3,a)
6、資料型別
序號 |
名稱 |
說明 |
1 |
number |
數值型 |
2 |
boolean |
布林型,true和False |
3 |
String |
字串 |
4 |
Null |
只有一個null值 |
5 |
Undefined |
變數宣告未賦值的 |
6 |
Symbol |
Es6新引入的型別 |
7 |
object型別 |
以上基本型別的複合型別,容器 |
ES是動態弱語言,弱型別語言,雖然先聲明瞭變數,但是變數可以重新賦值任何型別。
//string
console.log('----string-------')
console.log(a = 3+'abc',typeof(a))
console.log(a = null + 'abc',typeof(a))
console.log(a = undefined + 'abc',typeof(a))
console.log(a = true + 'abc',typeof(a))
//number
console.log('----number----')
console.log(a = null + 1,typeof(a))
console.log(a = undefined + 1,typeof(a)) //undefined沒有辦法轉成對應的數字,只是顯示男,not a number
console.log(a = true + 8,typeof(a))
console.log(a = false + 8,typeof(a))
//boolean
console.log('----bool----')
console.log(a = null + true,typeof(a))
console.log(a = null + false,typeof(a))
console.log(a = undefined + true,typeof(a)) //undefined沒有辦法轉成對應的數字
console.log(a = undefined + false,typeof(a)) //undefined,不能轉成對應的數字
console.log(a = null & true,typeof(a))
console.log(a = undefined & true,typeof(a))
//短路
console.log(a = null && true,typeof(a))
console.log(a = false && null,typeof(a))
console.log(a = false && 'abc',typeof(a))
console.log(a = true && 'abc',typeof(a))
console.log(a = true && '',typeof(a))
//null
console.log(a = null + undefined,typeof(a))
----string-------
3abc string
nullabc string
undefinedabc string
trueabc string
----number----
1 'number'
NaN 'number'
9 'number'
8 'number'
----bool----
1 'number'
0 'number'
NaN 'number'
NaN 'number'
0 'number'
0 'number'
null 'object'
false 'boolean'
false 'boolean'
abc string
string
NaN 'number'
型別運算:
String:與str相加全部轉化為str型別。
Number:與number相加全部轉化為number
Boolean型別:轉為話number型別
弱型別,不需要強制型別轉換,會隱士的型別轉換。
總結:
遇到字串,加號就是拼接字串。
如果沒有遇到字串,加號就是把其他的所有的型別都當做數字處理。
Undefined特殊,因為他沒有定義值,所以是一個特殊的數字nan.
如果運算子是邏輯運算子,短路符,返回的就是短路時候的型別,沒有隱士轉換,
儘量使用顯示的轉換。
7、字串
將一個值利用單引號或者雙引號引起來就是字串。
Es6提供了反引號定義一個字串,可以支援多行,還可以支援插值。
字串:插值。使用反引號$符號進行插值,賦值即定義。
let a = 'abc'
let b = 'ced'
let c = `line1
line2
line3
`
console.log(c)
let name = 'tom',age = 19
console.log(`hi name is ${name},age${age}`)
line1
line2
line3
hi name is tom,age19
8、轉義字元
名稱 |
說明 |
\0 |
Null位元組 |
\b |
退格符 |
\f |
換頁符 |
\n |
換行符 |
\r |
回車符 |
\t |
Tab製表符 |
\v |
垂直製表符 |
\’ |
單引號 |
\” |
雙引號 |
\ |
反斜槓符(\) |
\XXX |
由從0到377最多三位八進位制數XXX,例如\251是版權符號的八進位制序列 |
\xXX |
由從00和FF的兩位十六進位制數字XX表示的Latin-1字元。\ x A9是版權符號的十六進位制序列 |
\uXXXX |
由思維十六進位制數字XXXX的Unicode字元,例如,\u 00A9是版權符號的Unicode序列。見Unicode escape sequences(Unicode轉義字元) |
\u{XXXXX} |
Unicode程式碼點(code point)轉義字元,例如\u{2F804}相當於Unicode轉義字元\uD87E\uDc04的簡寫。 |
9、字串操作方法
let a = 'abcdefgh'
console.log(a.charAt(2)) //索引查詢字串
console.log(a[2]) //索引查詢字串
console.log(a.toUpperCase()) // 大寫
console.log(a.concat('.com')) //拼接字串
console.log(a.slice(3)) // 切片
console.log(a.slice(3,6)) //
console.log(a.slice(-2,-1)) //負索引切片
console.log(a.slice(-2)) //負索引切片
c
c
ABCDEFGH
abcdefgh.com
defgh
def
g
gh
let url = 'www.google.com'
console.log(url.split('.')) //以什麼進行切割
console.log(url.substr(7,2)) // 返回字串從何處開始,取多長
console.log(url.substring(7,10)) // 返回子串,從何處開始,到什麼為止
[ 'www', 'google', 'com' ]
gl
gle
let url1 = 'www.google.com'
console.log(url1.indexOf('com')) // 查詢字串所在的索引
console.log(url1.replace('.com','.cn')) //替換
console.log(url1.indexOf('gle',3)) // 向右偏移3
url2 = '\tmg edu \r\n'
console.log(url2.trim()) //去除兩端的空白字串
11
www.google.cn
7
mg edu
10、數值型number
在js中,資料均為雙精度浮點型範圍只能在- +(2^53-1)之間,整型不例外。
數字型別還有三種符號值:+infinity(正無窮) -infinity(負無窮)和nan(not-a-number非數字)
二進位制0b。
八進位制0o
十六進位制0x
指數表示1E3(1000),2e-2(0.02)
常量屬性:
數字的方法;
方法 |
描述 |
Number.parseFloat() |
把字串引數解析成浮點數,和全域性方法parseFloat()作用一致 |
Number.parseInt() |
把字串解析成特定基數對應的整型數字,和全域性方法parseInt()作用一致 |
Number.isFinite() |
判斷傳遞的值是否為有限的數字 |
Number.isInteger() |
判斷傳遞的值是否為整數 |
Number.isNaN() |
判斷傳遞的值是否為NaN |
內建數學物件:Math
有絕對值,對數、指數運算、三角函式運算、最大值、最小值、隨機數、開方等運算函式。
console.log(Math.PI) //3.14 PI值
console.log(Math.abs(-1)) //絕對值
console.log(Math.log2(16)) // 開方
console.log(Math.sqrt(2)) //平方根
console.log(Math.random()) //隨機數
11、運算子
1)算數運算子
+ - * / %
console.log(1/2) //0.5
console.log(1/0) //Infinity
console.log(5%3) //2
console.log(parseInt(1/2)) // 0 向下取整
console.log(parseInt(3/2)) // 1 向下取整
console.log(Math.floor(3/2)) // 1 向下取整
console.log(Math.ceil(3/2)) // 2 向下取整
console.log(Math.round(3/2)) // 2 四捨五入
console.log(Math.round(1/2)) // 1 四捨五入
++和—
單目運算子,表示變數自增,自減
I++ 先用i,用完之後在加1
++I i先自增,在使用i
let i = 0
let a = i++
console.log(a,i) //0 1
console.log(a,i++) // 0 1
a = ++ i
console.log(a,i) // 3 3
單目運算子是優先順序高於雙目運算子。
7
i = 0;
let a = ++i+i+++i+++i; //++i + i++ i++ +i
console.log(a); // 1 1 2 3 7
2)比較運算子
不做隱士的型別轉換寫的是===。
不做兩個等等號。嚴格相等使用三個等號。
console.log(100 > '200') // false
console.log(100 > 'a') //false
console.log(300 == '300') //true
console.log(300 === '300') //false
3)邏輯運算子
&&,||,! 與或非
4)位運算
& | ^ ~<< >>位與,位或,異或,取反,左移,右移。
5)三元運算子
條件表示式?真值:假值
console.log(('3' > 30)?'真':'假')
6)逗號操作符
Js執行多個表示式寫在一起
let a = 4+5,b = true,c=a > 20?'t':'f'
console.log(a) // 9
console.log(c) // f
7)其他
名稱 |
說明 |
Instanceof |
判斷是否屬於指定型別 |
Typeof |
判斷型別字串 |
Delete |
Delete操作符,刪除物件 |
In |
判斷指定的屬性在物件內,則返回true |
console.log('a' instanceof String) // false
console.log(1 instanceof Number) // false
a = new String('b')
console.log(a instanceof String) // true
console.log(new Number(1) instanceof Number) // true
console.log(a instanceof Object) // true
Instance必須明確使用的型別定義變數。沒有 new方法的型別的都不是初始的型別。可以用於繼承關係的判斷。
Typeof就是返回物件的型別字串。
Delete刪除物件、屬性、陣列元素
8)運算子優先順序
運算子由高到低。
var trees = new Array();
逗號運算子優先順序最低,比賦值語句還低。
9)表示式(生產器)
function* inc()
{
let i = 0;
let j = 2;
while(true){
yield i++
if (!j--)return 100;
}
}
let gen = inc()
for (let i = 0 ;i<10;i++)
console.log(gen.next());
{ value: 0, done: false }
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 100, done: true }
{ value: undefined, done: true }
{ value: undefined, done: true }
{ value: undefined, done: true }
{ value: undefined, done: true }
{ value: undefined, done: true }
{ value: undefined, done: true }
每次呼叫next()方法返回一個物件,這個物件包含兩個屬性:value和done,value屬性表示本次yield表示式的返回值,done屬性為布林值,done是False表示後續還有yield語句執行,如果執行完成或者return後,done為true。
三、js語法
1、語句塊
function hello(){
let a = 1;
var b = 2;
c =3
}
if (1)
{
let d = 4;
var e = 5;
f = 6
if (true){
console.log(d)
console.log(e)
console.log(f)
console.log('------')
g = 10
var h = 11
}
}
console.log(e)
console.log(f)
console.log(g)
console.log(h)
4
5
6
------
5
6
10
11
大括號中都是一個作用域。
Let定義的外部不能訪問,只能是內部才能訪問。Var塊作用域,外部可以見到,普通定義外部也可見。
2、條件分支
if (cond1){
}
else if(cond2){
}
else if (cond3){
}
else{
}
條件False等效
False
Undefined
Null
0
NaN
空字串(””)
3、switch..case分支語句
switch (expression){
case label_1
statements_1
[break;]
case label_2
statements_2
[break;]
default:
statements_def
[break;]
}
let x = 5
switch (x){
case 0:
console.log('zero')
break;
case 1:
console.log('one')
case 2:
console.log('two')
case 3:
console.log('three')
break;
case 4:
console.log('four')
default:
console.log('other')
break;
}
Switch…case語句都可以協程多分支結構。
4、for迴圈
//for ([initialExpression];[condition];[increamentExpression])
//{
// statement
//}
for (let i=0;i<10;i++){
console.log(i)
}
console.log('---')
5、while迴圈和do….while迴圈
While (condition)
Statement
條件滿足,進入迴圈,條件為真,繼續迴圈
do
statement
while (condition);
先進入迴圈,然後判斷,為真就繼續迴圈。
let x = 10;
while(x--){
console.log(x);
}
do{
console.log(x);
}while(x++<10)
列印九九乘法表:
for (let x = 1;x<10;x++)
{
line = '';
for(let y = 1;y<=x;y++)
line += `${x}*${y}=${x*y}`;
console.log(line)
}
5、for…in 迴圈
物件操作語句for…in用來遍歷物件的屬性
for (variable in object){
statements}
let arr =[10,20,30,40 ]
console.log(arr[2]) //30
for (let x in arr)
console.log(x)
for (let index in arr)
console.log(`${index}:${arr[index]}`);
for (let i=0;i<arr.length;i++)
console.log(arr[i]);
let obj = {
a:1,
b:'abc',
c:true
};
console.log(obj.a)
console.log(obj['b'])
console.log(obj.d)
console.log('++++++')
for (let x in obj)
console.log(x) //屬性名
for (let key in obj) //返回陣列的index
console.log(`${key}:${obj[key]}`);
30
0
1
2
3
0:10
1:20
2:30
3:40
10
20
30
40
1
abc
undefined
++++++
a
b
c
a:1
b:abc
c:true
for in 迴圈返回的是索引或者key,需要簡介訪問到值。
陣列反正返回的是索引,c風格for迴圈操作簡單。
6、for..of迴圈
Es6的新語法
let arr = [1,2,3,4,5]
let obj = {
a;1,
b:'abc',
c:true
}
for (let i of arr){ //返回陣列的元素
console.log(i)
}
for (let i of obj){ //異常,不可以迭代
console.log(i)
}
For….of不能是迭代物件。
原因是of後面必須是一個迭代器(typeerror)
break 、continue
break結束當前迴圈
continue中斷當前煦暖,直接進入下一次迴圈。
7、for迭代的差別
function sum(arr){
for (let x in arr){
console.log(x,typeof(x),arr[x]);
}
for (let x of arr){
console.log(x,typeof(x));
}
for (let x = 0;x<arr.length;x++){
console.log(x,typeof(x),arr[x])
}
}
X退出的時候還是會加一或減一。
四、函式及作用域
1、函式表示式
function //函式名(引數列表){
//函式體;
return //返回值;
}
function add(x,y){
return x + y
}
console.log(add(3,5))
匿名函式表示式
const add = function(x,y){
return x + y;
};
console.log(add(4,5))
有名字的函式表示式
const add1 = function fn(x,y){
return x + y;
};
console.log(add1(3,4))
有名字的函式表示式,名字只能內部使用,外部不可見
const add2 = function _add(n){
if (n === 1) return n;
return n+ _add(--n)
};
console.log(add2(5))
函式、匿名函式、函式表示式的差異
函式和匿名函式,本質上是一樣的,都是函式物件,不過函式都有自己的識別符號,函式名,匿名函式需要的是藉助其他的識別符號而已。
區別在於,函式會宣告提升,函式表示式不會。
console.log(add(3,4))
function add(x,y){ //宣告提升
return x + y;
};
console.log(sub(4,5)) //會報出異常的,提示sub未定義
const sub = function(x,y){
return x + y;
};
定義函式的形式:function表示式。(有名字和匿名的),有名字的內部使用等。
宣告先做,呼叫後做。
生成器:
const counter = (function *(){
count = 1
while(1)
yield count ++;
})();
console.log(counter.next())
2、高階函式
高階函式:函式作為引數或者返回一個函式。
const counter = function(){
let c = 0;
return function(){
return c++
};
};
const c = counter()
console.log(c())
console.log(c())
map函式的實現
const map = function(arr,fn){
newarr = []
for (i in arr){
newarr[i] = fn(arr[i])
}
return newarr
};
console.log(map([1,2,3,4],function(x){
return ++x
}));
3、箭頭函式
const map1 = function(arr,fn){
newarr = []
for (i in arr){
newarr[i] = fn(arr[i])
}
return newarr
}
console.log(map([1,2,3,4],x =>++x))
// console.log(map1([1,2,3,4],x =>++x))
// console.log(map1([1,2,3,4],x=>{return ++x}))
console.log(map1([1,2,3,4],(x)=>{return ++x}))
箭頭函式就是匿名函式定義。
去掉關鍵字function。
一個引數的時候可以省掉括號。無參和多引數的時候必須保留括號。多個引數使用逗號分隔。
有大括號的時候必須有return。
定義是定義的形式。呼叫必須加括號,因為有優先順序的問題,所以呼叫前面的利用括號抱起來。
箭頭函式的返回值:
如果函式體部分有多行,就需要使用{},如果有返回值使用關鍵字return。
如果只有一行語句,可以同時省略大括號和return。
只要有return語句,就不能省略大括號,有return必須有大括號。
只有一條非return語句,加上大括號,函式就是沒有返回值了。
Map函式:
function map(arr,fn){
newarr1 = []
for (i in arr)
newarr1[i] = fn(arr[i])
return newarr1
};
console.log(map([1,2,3,4],function(x){
return ++x;
}));
4、引數
傳參是按照位置對應的,沒有關鍵字傳參這個屬性。寫的像的話只是賦值語句。
傳參的是隻是表示式的值。
陣列不解構的話當做一個來進行,解構利用…
預設值可以進行定義的。位置傳參的,預設值往後寫
//位置傳參
const add = (x,y)=> x+y;
console.log(add(4,5));
//預設值
const add1 = (x,y=6)=>x+y;
console.log(add1(4))
//非關鍵字傳參,沒有關鍵字傳參,只是表示式
const add2 = (x,y)=>x+y;
console.log(add2(z=1,c=2))
//預設值不能放在前,否則就是轉換為3和undefined相加,加過為NaN
const add3 = (x=1,y)=>x+y;
console.log(add3(3)) //NaN
5、可變引數
(1)args
const sum = function(...args){
let resule = 0;
for (i in args){
resule += args[i]
};
return resule
};
console.log(sum(2,3,4))
可變引數使用…args.
(2)arguments物件
const sum = function(...args){
let resule = 0;
console.log(arguments)
for (i in args){
resule += args[i]
};
return resule
};
console.log(sum(2,3,4))
{ '0': 2, '1': 3, '2': 4 }
所有的引數會儲存到一個k,v,鍵值對的字典裡面。
(3)引數解構
const add = function (x,y){
return x+y
}
console.log(add(...[100,200,300,400,500])) //引數解構,不需要引數一一對應的。
引數解構,不需要和需要的引數一一對應。
6、返回值
Return的返回值:返回的通常是幾個引數,返回的是最後一個引數的值。逗號表示式的。
const add1 = (x,y)=>{return x,y}
console.log(add1(1,2))
表示式的值:
逗號表示式,最後一個的值。
返回 的都只是一個單值。
a = (x = 5,y=6,true);
console.log(a)
b = (x=1,y=4,'abc');
console.log(b)
function c() {
return x= 1,y=2,'abc',false;
}
console.log(c());
7、作用域
Function函式定義,是獨立的作用域,內部定義的變數外部不可以見到。
//函式作用域
function c(){
a = 1
var b = 2
let c1 = 3
};
c();
console.log(a)
//console.log(b) // 函式中var定義變數沒有方法突破,外界見不到
//console.log(c1) // let定義的外界見不到
//塊作用域
if (1){
d = 4
var e = 5
let f = 6
}
console.log(d)
console.log(e) //var 塊中定義的才會外界可以見到。
// console.log(f) //let定義外界始終見不到
var b = 2可以提升宣告,可以突破非函式的塊作用域。
a = 1 隱士宣告不能進行提升宣告,
let a=3不能提升宣告。
嚴格模式:使用”use strict”語句放到函式的首行,或者js指令碼首行。
function show(i,args){
console.log(i,args)
};
x = 100;
function fn(){
let z = 200;
{
var a = 300;
show(1,x)
t = 'free'
let p = 400;
}
var y = 500
show(2,z)
show(3,x)
show(4,a)
show(5,t)
//show(5.5,p) //異常,let出不來上一個語句塊
{
show(6,y);
show(7,a)
show(8,t)
{
show(9,a)
show(10,t)
show(11,z)
}
}
}
fn()
// show(12,y) //異常,出不了函式的y
show(13,t)
// show(14,a) //異常,a不能出函式的
show(15,z) //變數宣告提升,聲明瞭z,但是還沒賦值
var z = 10;
五、js物件模型
基於原型的面嚮物件語言,而不是基於類的面嚮物件語言。
基於物件事件。
Js是基於原型的語言,只有原型物件的概念,原型物件就是一個模板,新的物件從這個物件模板構建從而獲取最初的屬性,任何物件在執行時候可以動態的增加屬性。任何一個物件都可以作為另一個物件的原型,後者就可以共享前者的屬性。
1、定義類
var obj = {
}
var obj1 = new Object();
var obj2 = new Object;
建立的時候必須使用new方法。
function定義的時候 大駝峰。
字面宣告方式。
2、es6之前---構造器
function Point(x,y){
this.x = x
this.y = y
this.show = ()=>console.log(1,this,this.x,this.y)
};
console.log(Point)
p1 = new Point(4,5)
console.log(2,p1)
function Point3D(x,y,z){
Point.call(this,x,y);
this.z = z
console.log(3,'Point 3d')
};
console.log(4,Point3D)
p2 = new Point3D(3,4,5)
console.log(5,p2)
p2.show();
[Function: Point]
2 Point { x: 4, y: 5, show: [Function] }
4 [Function: Point3D]
3 'Point 3d'
5 Point3D { x: 3, y: 4, show: [Function], z: 5 }
1 Point3D { x: 3, y: 4, show: [Function], z: 5 } 3 4
(1)定義一個函式(構造器)物件,函式名首字母大寫。
(2)This指代是當前例項的本身。定義屬性。
(3)使用new和構造器建立一個通用物件。New操作符會將新的物件的this值傳遞給point3d構造器函式,函式為這個物件建立z屬性。
如果不使用new方法,就是普通的函式呼叫,this不代表例項。
3、es6中的class
(1)class
Es6開始,提供了關鍵字class,建立物件更加簡單、清晰。
(1)利用關鍵字class,建立的本質上還是一個函式,是特殊的函式。
(2)一個類只能擁有一個名為constructor的構造器方法,如果沒有顯示定義一個構造方法,,就會預設新增一個constructor方法。
(3)繼承使用extends關鍵字
(4)一個構造器可以使用super關鍵字來呼叫父類的建構函式。
(5)類沒有私有屬性。
class Point{
constructor(x,y){
this.x = x
this.y = y
}
show(){
console.log(this,this.x,this.y)
}
}
let p1 = new Point(10,11)
p1.show()
class Point3D extends Point{
constructor(x,y,z){
super(x,y);
this.z = z
}
}
let p2 = new Point3D(4,5,6)
p2.show()
Point { x: 10, y: 11 } 10 11
Point3D { x: 4, y: 5, z: 6 } 4 5
重新寫show方法;
class Point{
constructor(x,y){
this.x = x
this.y = y
}
show(){
console.log(this,this.x,this.y)
}
}
p1 = new Point(1,2)
console.log(p1)
class Point3D extends Point{
constructor(x,y,z){
super(x,y)
this.z= z
}
show(){
console.log(this ,this.x,this.y,this.z)
}
}
p2 = new Point3D(3,4,5)
console.log(p2)
子類中直接重寫父類的方法即可,如果需要使用父類的方法,使用super.method()的方式呼叫。
使用箭頭函式修改:
class Point{
constructor(x,y){
this.x = x
this.y = y
this.show = ()=>console.log('point')
}
}
//繼承關係
class Point3D extends Point{
constructor (x,y,z){
super(x,y,z)
this.z = z
this.show=()=>console.log('point3d')
}
}
let p2 = new Point3D(3,4,5);
p2.show()
point3d
子類覆蓋,最終顯示的結果是point
class Point{
constructor(x,y){
this.x = x
this.y = y
this.show =()=>
console.log('point')
}
}
class Point3D extends Point{
constructor(x,y,z){
super(x,y)
this.z = z
//this.show=()=>console.log('Point3d')
}
show(){
console.log('point3d')
}
}
優先使用例項的方法,show方法,使用this的方法。
class Point{
constructor(x,y){
this.x = x
this.y = y
//this.show =()=>
// console.log('point')
}
show(){
console.log(this,this.x,this.y)
}
}
class Point3D extends Point{
constructor(x,y,z){
super(x,y)
this.z = z
this.show=()=>console.log('Point3d')
}
//show(){
// console.log('point3d')
//}
}
let p1 = new Point3D(2,3,4)
console.log(p1)
p1.show()
屬性優先,一定先用屬性。優先使用子類的屬性。
總結:如果子類和父類使用同一種方式進行定義,子類覆蓋父類的。
如果父類使用的屬性,子類使用的是方法,那麼就是採用父類的屬性。
如果子類使用的屬性,父類是方法,那麼優先使用的是子類的屬性方法。。
最終總結,屬性優先。。同一類定義的,子類優先
靜態屬性:
靜態方法沒有很好的支援的。
(2)靜態方法:
在方法名前面加上static,就是靜態方法了。
class Add{
constructor(x,y){
this.x = x
this.y = y
}
static show(){
console.log(this.x) //this是Add 不是Add的例項
}
}
a = new Add(2,3)
console.log(a)
//a.show() 例項不能直接訪問靜態方法
a.constructor.show() //例項可以通過constructor構造器方法訪問靜態方法。
靜態方法總結:例項不能直接訪問靜態方法,例項必須通過constructor方法訪問靜態方法。
靜態成員必須使用類來定義的。
例項是自己的。
4、this的坑
var shcool = {
name : 'abc',
getNameFunc: function(){
console.log(1,this.name)
console.log(2,this)
return function(){
console.log(3,this === global);
return this.name
}
}
};
console.log(4,shcool.getNameFunc()());
this是全域性的global的,所以第三行是true。
第四行,This是global的,所喲下面的return this.name沒有name屬性。
函式呼叫的時候呼叫的方式不用,this的物件就是不同的。
函式執行的時候,會開啟新的執行上下文環境executioncontext。
建立this屬性。
(1)myfunction(1,2,3)普通的函式呼叫,this指向的是全域性物件,全域性物件是nodejs的global或者瀏覽器的window。
(2)myObject.myFunction(1,2,3),物件的方法呼叫方式,this指向包含該方法的物件。
(3)call和apply方法的呼叫,都要看第一個引數是誰。
解決this的問題。
1)顯式傳入
var shcool1 = {
name : 'cde',
getNameFunc1 : function(){
console.log(this.name)
console.log(this);
return function(that){
console.log(this === global);
return that.name;
}
}
}
console.log(shcool1.getNameFunc1()(shcool1))
cde
{ name: 'cde', getNameFunc1: [Function: getNameFunc1] }
true
cde
利用關鍵字that 傳入物件。主動傳入物件,避開了this的問題
2)引入call、apply方法。
var shcool2 = {
name : 'asd',
getNameFunc2:function(){
console.log(this.name)
console.log(this);
return function(){
console.log(this === global);
return this.name
}
}
}
console.log(shcool2.getNameFunc2().call(shcool2));
asd
{ name: 'asd', getNameFunc2: [Function: getNameFunc2] }
false
asd
call方法和apply都是函式物件的方法,第一引數都是傳入物件引入的。
Apply傳其他引數需要陣列。
Call傳其他引數需要使用可變引數收集。
3)bind方法
var school3 = {
name: 'asdd',
getNameFunc3:function(){
console.log(1,this.name)
console.log(2,this)
return function(){
console.log(3,this === global);
return this.name;
}
}
};
// console.log(school3.getNameFunc3().bind(school3));
var func = school3.getNameFunc3()
console.log(4,func)
var bindfunc = func.bind(school3)
console.log(5,bindfunc)
console.log(6,bindfunc())
1 'asdd'
2 { name: 'asdd', getNameFunc3: [Function: getNameFunc3] }
4 [Function]
5 [Function: bound ]
3 false
6 'asdd'
Apply、call方法,引數不同,呼叫時候傳入this。
。bind方法是為函式繫結this,呼叫時候直接呼叫
4)es6引入的箭頭函式定義
var school = {
name :'ass',
getNameFunc:function(){
console.log(this)
console.log(this.name)
return ()=>{
console.log(this === global);
return this.name
}
}
};
console.log(school.getNameFunc()())
{ name: 'ass', getNameFunc: [Function: getNameFunc] }
ass
false
ass
class school{
constructor(){
this.name = 'abcd';
}
getNameFunc(){
console.log(this.name)
&nb