、什么是面向對象?
面向對象僅僅是一個概念或者編程思想
通過一種叫做原型的方式來實現面向對象編程
1、 創建對象(自定義對象,內置對象)
基于Object對象的方式創建對象-自定義對象
示例:
var 對象名稱=new Object( );
var flower=new Object();
flower.name="長春花";
flower.genera="夾竹桃科 長春花屬";
flower.area="非洲、亞熱帶、熱帶以及中國大陸的華東、西南、中南等地";
flower.uses="觀賞或用藥等";
flower.showName=function(){ alert(this.name); }
flower.showName();
常見的內置對象
String(字符串)對象
Date(日期)對象
Array(數組)對象
Boolean(邏輯)對象
Math(算數)對象
RegExp對象
二、
如何解決使用同一個接口不需要創建很多對象,減少產生大量的重復代碼?
1、構造函數:
function Flower(name,genera,area,uses){
this.name=name;
…….
this.showName=function(){
alert(this.name);
}
}
var flower1=new Flower("長春花","夾竹桃科 長春花屬","非洲、亞熱帶、熱帶以及中國大陸的華東、西南、中南等地","觀賞或用藥等")
flower1.showName();
2、原型對象:
function Flower(){
}
Flower.prototype.name="曼陀羅花";
Flower.prototype.genera="茄科 曼陀羅屬";
Flower.prototype.area="印度、中國北部";
Flower.prototype.uses="觀賞或藥用";
Flower.prototype.showName=function() {
alert(this.name);
}
var flower1=new Flower();
flower1.showName();
var flower2=new Flower();
flower2.showName();
alert(flower1.showName==flower2.showName);
三、繼承
1.原型鏈:一個原型對象是另一個原型對象的實例
相關的原型對象層層遞進,就構成了實例與原型的鏈條,就是原型鏈
示例:
function Humans(){
this.foot=2;
}
Humans.prototype.getFoot=function(){
return this.foot;
}
function Man(){
this.head=1;
}
Man.prototype=new Humans(); //繼承了Humans
Man.prototype.getHead=function(){
return this.head;
}
var man1=new Man();
alert(man1.getFoot()); //2
alert(man1 instanceof Object); //true
alert(man1 instanceof Humans); //true
alert(man1 instanceof Man); //true
2.對象繼承:
function Humans(){
this.clothing=["trousers","dress","jacket"];
}
function Man(){ }
//繼承了Humans
Man.prototype=new Humans();
var man1=new Man();
man1.clothing.push("coat");
alert(man1.clothing);
var man2=new Man();
alert(man2.clothing);
3.組合繼承:
組合繼承:有時也叫做偽經典繼承
將原型鏈和借用構造函數的技術組合到一塊,發揮二者之長的一種繼承模式
使用原型鏈實現對原型屬性和方法的繼承,而通過借用構造函數來實現對實例屬性的繼承
四、這一章的示例代碼:
<html>
<head>
<title>面向對象標題欄替換和修改</title>
</head>
<style>
* {
margin: 0;
padding: 0;
}
ul li {
list-style: none;
}
main {
width: 960px;
height: 500px;
border-radius: 10px;
margin: 50px auto;
}
main h4 {
height: 100px;
line-height: 100px;
text-align: center;
}
.tabsbox {
width: 900px;
margin: 0 auto;
height: 400px;
border: 1px solid lightsalmon;
position: relative;
}
nav ul {
overflow: hidden;
}
nav ul li {
float: left;
width: 100px;
height: 50px;
line-height: 50px;
text-align: center;
border-right: 1px solid #ccc;
position: relative;
}
nav ul li.liactive {
border-bottom: 2px solid #fff;
z-index: 9;
}
#tab input {
width: 80%;
height: 60%;
}
nav ul li span:last-child {
position: absolute;
user-select: none;
font-size: 12px;
top: -18px;
right: 0;
display: inline-block;
height: 20px;
}
.tabadd {
position: absolute;
/* width: 100px; */
top: 0;
right: 0;
}
.tabadd span {
display: block;
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
border: 1px solid #ccc;
float: right;
margin: 10px;
user-select: none;
}
.tabscon {
width: 100%;
height: 300px;
position: absolute;
padding: 30px;
top: 50px;
left: 0px;
box-sizing: border-box;
border-top: 1px solid #ccc;
}
.tabscon section,
.tabscon section.conactive {
display: none;
width: 100%;
height: 100%;
}
.tabscon section.conactive {
display: block;
}
</style>
<body>
<main>
<h4>
JS面向對象 動態添加標簽頁
</h4>
<div class="tabsbox" id="tab">
<!-- tab標簽 -->
<nav class="fisrstnav">
<ul>
<li class="liactive"><span>測試1</span><span class="iconfont icon-guanbi"></span> </li>
<li><span>測試2</span><span class="iconfont icon-guanbi"></span> </li>
<li class="liactive"><span>測試3</span><span class="iconfont icon-guanbi"></span> </li>
</ul>
<div class="tabadd">
<span>+</span>
</div>
</nav>
<!-- tab內容 -->
<div class="tabscon">
<section class="conactive">測試1</section>
<section>測試2</section>
<section>測試3</section>
</div>
</div>
</main>
</body>
<script>
var that;
class Tab {
constructor(id) {
// 獲取元素
that = this;
this.main = document.querySelector(id);
this.add = this.main.querySelector('.tabadd');
// li的父元素
this.ul = this.main.querySelector('.fisrstnav ul:first-child');
// section 父元素
this.fsection = this.main.querySelector('.tabscon');
this.init();
}
init() {
this.updateNode();
// init 初始化操作讓相關的元素綁定事件
this.add.onclick = this.addTab;
for (var i = 0; i < this.lis.length; i++) {
this.lis[i].index = i;
this.lis[i].onclick = this.toggleTab;
this.remove[i].onclick = this.removeTab;
this.spans[i].ondblclick = this.editTab;
this.sections[i].ondblclick = this.editTab;
}
}
// 因為我們動態添加元素 需要從新獲取對應的元素
updateNode() {
this.lis = this.main.querySelectorAll('li');
this.sections = this.main.querySelectorAll('section');
this.remove = this.main.querySelectorAll('.icon-guanbi');
this.spans = this.main.querySelectorAll('.fisrstnav li span:first-child');
}
// 1. 切換功能
toggleTab() {
// console.log(this.index);
that.clearClass();
this.className = 'liactive';
that.sections[this.index].className = 'conactive';
}
// 清除所有li 和section 的類
clearClass() {
for (var i = 0; i < this.lis.length; i++) {
this.lis[i].className = '';
this.sections[i].className = '';
}
}
// 2. 添加功能
addTab() {
that.clearClass();
// (1) 創建li元素和section元素
var random = Math.random();
var li = '<li class="liactive"><span>新選項卡</span><span class="iconfont icon-guanbi"></span></li>';
var section = '<section class="conactive">測試 ' + random + '</section>';
// (2) 把這兩個元素追加到對應的父元素里面
that.ul.insertAdjacentHTML('beforeend', li);
that.fsection.insertAdjacentHTML('beforeend', section);
that.init();
}
// 3. 刪除功能
removeTab(e) {
e.stopPropagation(); // 阻止冒泡 防止觸發li 的切換點擊事件
var index = this.parentNode.index;
console.log(index);
// 根據索引號刪除對應的li 和section remove()方法可以直接刪除指定的元素
that.lis[index].remove();
that.sections[index].remove();
that.init();
// 當我們刪除的不是選中狀態的li 的時候,原來的選中狀態li保持不變
if (document.querySelector('.liactive')) return;
// 當我們刪除了選中狀態的這個li 的時候, 讓它的前一個li 處于選定狀態
index--;
// 手動調用我們的點擊事件 不需要鼠標觸發
that.lis[index] && that.lis[index].click();
}
// 4. 修改功能
editTab() {
var str = this.innerHTML;
// 雙擊禁止選定文字
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
// alert(11);
this.innerHTML = '<input type="text" />';
var input = this.children[0];
input.value = str;
input.select(); // 文本框里面的文字處于選定狀態
// 當我們離開文本框就把文本框里面的值給span
input.onblur = function () {
this.parentNode.innerHTML = this.value;
};
// 按下回車也可以把文本框里面的值給span
input.onkeyup = function (e) {
if (e.keyCode === 13) {
// 手動調用表單失去焦點事件 不需要鼠標離開操作
this.blur();
}
}
}
}
new Tab('#tab');
</script>
</html>
ava 內存模型中的 happen-before 是什么?
Happen-before 關系,是Java 內存模型中保證多線程可見性的機制,也是早期語言規范中含糊可見性概念的一個精確定義。
它的具體表現形式,包括但遠不止 synchronized,volatile,lock 操作順序等方面。
happen-before 保障了順序執行,也包括了內存讀寫的操作順序。
image
JMM 可以看作是深入理解Java并發編程、編譯器和JM內部機制的必要條件,但這同時也是個容易讓初學者無所適從的主題。
Java 是最早嘗試提供內存模型的語言,可簡化多線程編程,保障程序可移植。 早期的 C/C++ 不存在內存模型的概念,依賴處理器本身的內存一致性模型。 但是不同的處理器差異比較大,不能保證 C++ 程序在處理器A 可以運行,在處理器B 上也可以運行。
過于范范的內存模型定義,有很多模棱兩可之處,對 synchronized 或者 volatile 產生的指令重排序問題,如果沒有清晰的規范,不能保證一些多線程程序的正確性。
所以,Java迫切需要一個完善的JMM,能夠讓普通Java開發者和編譯器、JVM工程師,能夠淸地達成共識。換句話說,可以相對簡單并準確地判斷岀,多線程程序什么樣的執行序列是符合規范的。
對于編譯器、JVM開發者,關注點可能是如何使用類似內存屏( Memory-Barrier)之類技術,保證執行結果符合JMM的推斷。
對于Java應用開發者,則可能更加關注 volatile、 synchronized等語義,如何利用類{ happen- before的規則,寫出可靠的多線程應用。
image
包含本地內存和主內存的定義
image
內存屏障能夠在類似變量讀、寫操作之后,保證其他線程對 volatile變量的修改對當前線程可見,或者本地修改對其他線程提倛可見性。換句話說,線程寫入,寫屏障會通過類似強迫刷出處理器緩存的方式,讓其他線程能夠拿到最新數值。
如果你對更多內存屏障的細節感興趣,或者想了解不同體系結構的處理器模型,建議參考JSR-133相關文檔,我個人認為這些都是和特定硬件相關的,內存屏障之類只是實現JMM規范的技術手段,并不是規范的要求。
class VolatileExample {
int a = 0;
volatile boolean flag= false;
public void writer(){
a=1; // 1
flag = true; //2
}
public void reader(){
if(flag){ //3
int i = a ;//4
...
}
}
假設線程A執行 writer方法之后,線程B執行 reader0方法。根據 happens-before規則,這個過程建立的 happens-before關系可以分為3類:
上述 happens-before關系的圖形化表現形式如下:
image
在上圖中,每一個箭頭鏈接的兩個節點,代表了一個 happens-before關系。黑色箭頭表示程序順序規則;橙色箭頭表示 volatile規則;藍色箭頭表示組合這些規則后提供的 happens-before保證。 最終讀取到的i 就是 1 。
image
線程A在寫flag變量后,本地內存A中被線程A更新過的兩個共享變量的值被刷新到主內存中。此時,本地內存A和主內存中的共享變量的值是一致的。
當讀一個 volatile變量時,JMM會把該線程對應的本地內存置為無效。線程接下來將從主內存中讀取共享變量。如圖所示,在讀flag變量后,本地內存B包含的值已經被置為無效。此時,線程B必須從主內存中讀取共享變量。線程B的讀取操作將導致本地內存B與主內存中的共享變量的值變成一致。
image
有序性,原子性,可見性是線程安全的基本保障。
image
我們經常會說 volatile b比synchronized之類更加輕量,但輕量也僅僅是相對的, volatile的讀、寫仍然要比普通的讀寫要開銷更大,所以如果你是在性能高度敏感的場景,除非你確定需要它的語義,不然慎用。
近因為一些網頁的需要,需要比較深入的使用了CSS 的「偽元素」( Pseudo Element ),發現原來不只是用用before或after 而已,可以玩的東西還真是不少,所以就來篇文章,把這些比較不常玩的用法歸納整理下,希望對你的日常工作有所幫助。
「偽元素」之所以稱作「偽」,除了英文從「Pseudo」翻譯過來之外,就是因為它并不是真正網頁里的元素,但行為與表現又和真正網頁元素一樣,也可以對其使用CSS 操控。
跟偽元素類似的還有「偽類」( Pseudo classes ),在W3C的定義里總共有五個偽元素(其他仍在測試階段),分別是::before、::after、::first-line、::first-letter和::selection,為了和偽類區分,偽元素使用兩個冒號「::」開頭,而偽類使用一個冒號「:」開頭(像是:hover、:target...等)。
雖然現在的瀏覽器就算寫一個冒號也可以正常運作,不過為了方便區分,用兩個冒號還是比較好的,而且不論瀏覽器是什么,::selection必須是兩個冒號才能正常運作。
參考:MDN Pseudo-elements、偽類child和of-type
::before、::after大概是最常使用的偽元素,兩者都是以display:inline-block的屬性存在,::before是在原本的元素「之前」加入內容,::after則是在原本的元素「之后」加入內容,同時偽元素也會「繼承」原本元素的屬性,如果原本文字是黑色,偽元素的文字也會是黑色。
舉例來說,下面這段程式碼,有一個div 內容是「大家好,我是div」,使用::before、::after 之后,會在原本div 的前后各添加一段文字,并且讓這兩段文字都呈現紅色。
div::before{ content:"我是 before"; color:red; } div::after{ content:"我是 after"; color:red; }
上述的內容乍看之下很容易理解,比較需要注意的是一定要具備content的屬性,就算是只有content:"";都可以,因為沒有content的偽元素是不會出現在畫面上的,然而content是個很特別的屬性,它可以使用attr直接獲取內容元素的屬性值( attribute ),舉例來說,在HTML里有一個超連結,點擊后會彈出新視窗并連結至Google:
<a target="_blank">google</a>
使用下列的程式碼用法,將會把超連結的href 內容與target 內容,透過偽元素一前一后的顯示出來。
a::before{ content: attr(href); color:red; } a::after{ content: attr(target); color:green; }
此外content內容是可以「相加」的,不過用法不像JavaScript使用+號來相連,而是直接用一個空白鍵就可以不斷的累加下去,以下面的程式碼來說,可以在剛剛擷取的超連結文字后方和target屬性前方,加入標點符號。
a::before{ content: "( " attr(href) " ) < "; color:red; } a::after{ content: " > ( " attr(target) " ) "; color:green; }
content 甚至可以使用url 放入圖片的功能,下列的程式碼會呈現出三張圖片。
div::before{ content:url(圖片網址) url(圖片網址) url(圖片網址); }
通過調整border的屬性,我們可以實現上下左右的三角形,再結合偽元素before,after,content可以繪制多種多邊形,筆者在這篇文章有過介紹,感興趣的可以看看 :只用1個div,你能用CSS繪制:正3、4、5、6、7、8邊形嗎?
在CSS里有個不常用的屬性就是quotes,這是做為定義「括號格式」的屬性,也就是如果在一段文字被包住,這段文字的前后就會出現自定義的標簽替換(可以是括號、特殊符合、文字等),而且quotes支持多層嵌套,也就是你可以一層層的寫下去,以下面這段HTML文字舉例:
最外層<q>第一層<q>第二層</q><q>第二層<q>第三層</q></q></q>
quotes 的屬性如果只寫一層,就會看到只出現一種括號,前后括號使用空白分隔,兩組為一個單位,前后可以不同符號。
q{ quotes: ' < ' ' > '; }
如果寫了三層,就會看到出現三種括號,也會把文字當作括號使用。
q{ quotes: ' < ' ' > ' ' ya ' ' ya ' ' ( ' ' ) ' ; }
(請注意開合標簽的就近分配原則)
同樣的道理,我們可以應用在content里面,而且通過偽元素::before和::after處于前后的預設位置,甚至不用就實現前后括號的效果,以下面這段HTML文字舉例,把剛剛的q全部換成span:
最外層<span>第一層<span>第二層</span><span>第二層<span>第三層</span></span></span>
CSS的部分比較特別,在偽元素content里使用了open-quote (啟始括號)和close-quote (結束括號)這兩個有趣的值,換句話說open-quote對應到,close-quote對應到,此外也由于括號是在偽元素內,就可以指定不同的顏色或樣式了。
span{ quotes: ' < ' ' > ' ' ya ' ' ya ' ' ( ' ' ) ' ; } span::before{ content:open-quote; color:red; } span::after{ content:close-quote; color:#aaa; }
文章來源:https://www.oxxostudio.tw/articles/201706/pseudo-element-1.html
原文作者:oxxostudio
由于網頁為繁體內容,術語描述和標點話術的差異的問題,筆者在保證不改變原意的基礎上做了調整,并且內容頁進行了驗證確認無誤,歡迎大家指正。
雖然說偽元素很好用,但偽元素的內容實際上不存在網頁里( 如果打開瀏覽器的開發者工具,是看不到內容的),所以如果在里頭塞了太多的重要的內容,反而會影響到SEO 的成效,因此對于使用偽元素的定位,還是當作「輔助」性質會比較恰當。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。