JavaScript中label与break配合使用

语法

label:
    statement

说明

label语句可以在代码中添加标签,以便将来使用。定义的标签可以在将来由break或continue语句引用。加标签的语句一般都要与for语句等循环语句配合使用。

// 示例
let count = 0;
loop1:
for (let i = 0; i < 10; ++i) {
    for (let j = 0; j < 10; ++j) {
        if (i === 6 && j === 6) {
            break loop1;
        }
        ++count;
    }
}
console.log(count); // 66

正常情况下break只会退出最近的一个循环,以上例子会返回96。但标记loop标记了最外层的for循环,所以break后便退出了整个循环。

一个循环内也可以有多个标记。

// 示例
let count = 0;
loop1:
for (let i = 0; i < 10; ++i) {
    loop2:
    for (let j = 0; j < 10; ++j) {
        for (let k = 0; k < 10; ++k) {
            if (i === 6 && j === 6 && k === 6) {
                break loop2;
            }
            ++count;
        }
    }
}
console.log(count); // 966

JavaScript数据结构与算法-集合练习

集合的实现

function Set () {
    this.dataStore = [];
    this.add = add;
    this.remove = remove;
    this.size = size;
    this.union = union;
    this.intersect = intersect;
    this.subset = subset;
    this.difference = difference;
    this.show = show;
    this.contains = contains;
}
function add (data) {
    if (this.dataStore.indexOf(data) < 0) {
        this.dataStore.push(data);
        return true;
    } else {
        return false;
    }
}
function remove (data) {
    let pos = this.dataStore.indexOf(data);
    if (pos > -1) {
        this.dataStore.splice(pos, 1);
        return true;
    } else {
        return false;
    }
}
function show () {
    return this.dataStore;
}
function contains (data) {
    if (this.dataStore.indexOf(data) > -1) {
        return true;
    } else {
        return false;
    }
}
function union (set) {
    let tempSet = new Set();
    for (let i = 0; i < this.dataStore.length; ++i) {
        tempSet.add(this.dataStore[i]);
    }
    for (let i = 0; i < set.dataStore.length; ++i) {
        if (!tempSet.contains(set.dataStore[i])) {
            tempSet.dataStore.push(set.dataStore[i]);
        }
    }
    return tempSet;
}
function intersect (set) {
    let tempSet = new Set();
    for (let i =0; i < this.dataStore.length; ++i) {
        if (set.contains(this.dataStore[i])) {
            tempSet.add(this.dataStore[i]);
        }
    }
    return tempSet;
}
function subset (set) {
    if (this.size() > set.size()) {
        return false;
    } else {
        for (let i = 0; i < this.dataStore.length; ++i) {
            if (!set.contains(this.dataStore[i])) {
                return false;
            }
        }
    }
    return true;
}
function size () {
    return this.dataStore.length;
}
function difference (set) {
    let tempSet = new Set();
    for (let i = 0; i < this.dataStore.length; ++i) {
        if (!set.contains(this.dataStore[i])) {
            tempSet.add(this.dataStore[i]);
        }
    }
    return tempSet;
}

练习

一. 修改集合类,使里面的元素按顺序存储。写一段测试代码来测试你的修改。

// 修改add方法
function add (data) {
    if (this.dataStore.indexOf(data) < 0) {
        this.dataStore.push(data);
        // 排序
        this.dataStore = this.dataStore.sort((a, b) => a - b);
        return true;
    } else {
        return false;
    }
}
// 示例
let s = new Set();
s.add(23);
s.add(3);
s.add(2);
s.add(24);
s.add(73);
console.log(s.show()); // [2, 3, 23, 24, 73]

二. 为集合类增加一个higher(element)方法,该方法返回比传入元素大的元素中最小的那个。写一段测试代码来测试这个方法。

Set.prototype.higher = function (element) {
    let arr = [];
    for (let i = 0; i < this.dataStore.length; ++i) {
        if (this.dataStore[i] > element) {
            arr.push(this.dataStore[i]);
        }
    }
    return arr.sort((a, b) => a - b)[0];
};
// 示例
let s = new Set();
s.add(23);
s.add(3);
s.add(2);
s.add(24);
s.add(73);
console.log(s.higher(20)); // 23
console.log(s.higher(60)); // 73

三. 为集合类增加一个lower(element)方法,该方法返回比传入元素小的元素中最大的那个。写一段测试代码来测试这个方法。

Set.prototype.lower = function (element) {
    let arr = [];
    for (let i = 0; i < this.dataStore.length; ++i) {
        if (this.dataStore[i] < element) {
            arr.push(this.dataStore[i]);
        }
    }
    return arr.sort((a, b) => b - a)[0];
};
// 示例
let s = new Set();
s.add(23);
s.add(3);
s.add(2);
s.add(24);
s.add(73);
console.log(s.lower(20)); // 3
console.log(s.lower(60)); // 24

JavaScript数据结构与算法-散列练习

散列的实现

// 散列类 - 线性探测法
function HashTable () {
    this.table = new Array(137);
    this.values = [];
    this.simpleHash = simpleHash;
    this.betterHash = betterHash;
    this.showDistro = showDistro;
    this.put = put;
    this.get = get;
}
function put (key, data) {
    let pos = this.betterHash(key);
    // this.table[pos] = data;
    if (this.table[pos] === undefined) {
        this.table[pos] = key;
        this.values[pos] = data;
    } else {
        while (this.table[pos] !== undefined) {
            ++pos;
        }
        this.table[pos] = key;
        this.values[pos] = data;
    }
}
function get (key) {
    // return this.table[this.betterHash(key)];
    let hash = -1;
    hash = this.betterHash(key);
    if (hash > -1) {
        for (let i = hash; this.table[hash] !== undefined; ++i) {
            if (this.table[hash] === key) {
                return this.values[hash];
            }
        }
    }
    return undefined;
}
function simpleHash (data) {
    let total = 0;
    for (let i = 0; i < data.length; ++i) {
        total += data.charCodeAt(i);
    }
    return total % this.table.length;
}
function showDistro () {
    let n = 0;
    for (let i = 0; i < this.table.length; ++i) {
        if (this.table[i] !== undefined) {
            console.log(`${i}: ${this.table[i]}`);
        }
    }
}
function betterHash (string) {
    const H = 7;
    let total = 0;
    for (let i = 0; i < string.length; ++i) {
        total += H * total + string.charCodeAt(i);
    }
    total = total % this.table.length;
    if (total < 0) {
        total += this.table.length -1;
    }
    return parseInt(total, 10);
}

练习

使用线性探测法创建一个字典,用来保存单词的定义。该程序需要包含两个部分:第一部分将一组单词和它们的定义存储进散列表;第二部分让用户输入单词,程序给出该单词的定义。

// 字典类
function Dict () {
    this.hashTable = new HashTable();
    this.save = save;
    this.find = find;
}
function save (word, description) {
    this.hashTable.put(word, description);
}
function find (word) {
    return this.hashTable.get(word);
}
// 示例
let d = new Dict();
d.save('Mazey', 'a strong man.');
d.save('Cherrie', 'a beautiful girl.');
d.save('John', 'unknown.');
console.log(d.find('John')); // unknown.
console.log(d.find('Mazey')); // a strong man.
console.log(d.find('Ada')); // undefined

HTML5全屏浏览器兼容方案

最近一个项目有页面全屏的的需求,搜索了下有HTML5的全屏API可用,不过各浏览器的支持不一样。

标准 webkit Firefox IE
Element.requestFullscreen() webkitRequestFullscreen mozRequestFullScreen msRequestFullscreen
Document.exitFullscreen() webkitExitFullscreen mozCancelFullScreen msExitFullscreen
Document.fullscreenElement webkitFullscreenElement mozFullScreenElement msFullscreenElement
Document.fullscreenEnabled webkitFullscreenEnabled mozFullScreenEnabled msFullscreenEnabled
Document.fullscreenchange webkitfullscreenchange mozfullscreenchange MSFullscreenChange
Document.fullscreenerror webkitfullscreenerror mozfullscreenerror MSFullscreenError

MDN Fullscreen API: The Fullscreen API provides an easy way for web content to be presented using the user's entire screen. The API lets you easily direct the browser to make an element and its children, if any, occupy the fullscreen, eliminating all browser user interface and other applications from the screen for the duration.

全屏接口提供了简单的方式通过用户整个屏幕展示浏览器的内容。这个接口让我们很轻松的引导浏览器使一个元素和它的子元素占据整个屏幕,并且从屏幕上消除所有浏览器用户界面和其它应用程序。

一、接口使用(以谷歌浏览器为例)

1.requestFullscreen()

全屏请求方法,使用方法:Element.requestFullscreen()

<div id="example">
    <img src="html5.png">
    <button type="button" id="requestFullscreen">requestFullscreen</button>
</div>

<script>
// 全屏
document.getElementById('requestFullscreen').addEventListener('click', () => {
    document.querySelector('img').webkitRequestFullscreen();
});
</script>

触发事件后会有按ESC即可退出全屏模式的文字提示。

注意

1.在< iframe >框架中使用全屏需要加allowfullscreen属性。
2.全屏请求只能通过用户操作触发,否则会出现Failed to execute 'requestFullscreen' on 'Element': API can only be initiated by a user gesture.这样的警告,解决办法是将此方法绑定到某个用户操作事件上,例如点击事件click

(function () {
    document.documentElement.webkitRequestFullscreen();
})();

2.exitFullscreen()

退出全屏模式的方法,使用方法:document.exitFullscreen(),除了requestFullscreen()其它方法和属性都是基于document的。

<div id="example">
    <img src="html5.png">
    <button type="button" id="requestFullscreen">requestFullscreen</button>
    <button type="button" id="exitFullscreen">exitFullscreen</button>
</div>

<script>
// 退出全屏
document.getElementById('exitFullscreen').addEventListener('click', () => {
    document.webkitExitFullscreen();
});
</script>

触发后退出全屏恢复页面原来的样子,也可以按ESC退出;另外F11也可以使页面全屏显示和退出,但这应该属于浏览器的功能,不在HTML5 API的范畴之内。

3.fullscreenElement

若是全屏模式下,显示全屏的元素,若不是,返回null

<div id="example">
    <img src="html5.png">
    <button type="button" id="requestFullscreen">requestFullscreen</button>
    <button type="button" id="exitFullscreen">exitFullscreen</button>
    <button type="button" id="fullscreenElement">fullscreenElement</button>
</div>

<script>
// 显示全屏元素
document.getElementById('fullscreenElement').addEventListener('click', () => {
    console.log(document.webkitFullscreenElement); // <div id=...></div> 或 null
});
</script>

4.fullscreenEnabled

返回一个布尔值true/false,判断是否可用全屏模式。

<div id="example">
    <img src="html5.png">
    <button type="button" id="fullscreenEnabled">fullscreenEnabled</button>
</div>

<script>
// 全屏是否可用
document.getElementById('fullscreenEnabled').addEventListener('click', () => {
    console.log(document.webkitFullscreenEnabled); // true
});
</script>

二、浏览器兼容

由于各主流浏览器调用全屏接口的方法不一致,所以调用之前需要判断一下当前浏览器适用的方法。

我简单的做了下请求全屏退出全屏的适配。

const MAZEY_FULL_SCREEN = function () {
    let prefixArr = ['', 'webkit', 'moz', 'ms'], // 浏览器前缀
        isRightRequest, // 是否找到适配的方法
        isRightExit,
        requestMethod, // 全屏方法
        exitMethod, // 退出全屏方法
        lowerFirst = function (str) {
            return str.slice(0, 1).toLowerCase() + str.slice(1);
        },
        requestSuffixArr = ['RequestFullscreen', 'RequestFullScreen'], // 后缀
        exitSuffixArr = ['ExitFullscreen', 'CancelFullScreen'],
        searchRightMethod = function (prefix, suffixArr, documentParent) {
            let methodArr = suffixArr.map((suffix) => {
                return prefix + suffix;
            }),
            method,
            isRight;
            methodArr.forEach((wholePrefix) => {
                if (isRight) return;
                if (prefix.length === 0) {
                    wholePrefix = lowerFirst(wholePrefix)
                }
                if (wholePrefix in documentParent) {
                    method = wholePrefix;
                    isRight = true;
                    // console.log(method);
                }
            });
            return method;
        };
    prefixArr.forEach((prefix) => {
        if (isRightRequest && isRightExit) return;
        // 查找请求
        requestMethod = searchRightMethod(prefix, requestSuffixArr, document.documentElement);
        isRightRequest = Boolean(requestMethod);
        // 查找退出
        exitMethod = searchRightMethod(prefix, exitSuffixArr, document);
        isRightExit = Boolean(exitMethod);
    });
    this.request = function (element) {
        let domEle = document.querySelector(element) || document.documentElement;
        domEle[requestMethod]();
    };
    this.exit = function () {
        document[exitMethod]();
    };
};

let fullscreen = new MAZEY_FULL_SCREEN();

使用示例:

<h1 id="h1">html5 - 全屏</h1>
<button id="request">请求</button>
<button id="exit">退出</button>
<script src="mazey-full-screen.js"></script>

<script>
// 请求全屏
document.getElementById('request').addEventListener('click', () => {
    fullscreen.request();
});
// 退出全屏
document.getElementById('exit').addEventListener('click', () => {
    fullscreen.exit();
});
</script>

示例代码:GitHub