改进:
所有三种方法应该在子类构造函数中调用父类构造函数实现实例属性初始化
function Rect() {
Shape.call(this);
}
用新创建的对象替代子类默认原型,设置Rect.prototype.constructor = Rect;保证一致性
第三种方法的polyfill:
function create(obj) {
if (Object.create) {
return Object.create(obj);
}
function f() {};
f.prototype = obj;
return new f();
}
$javascript编程部分
请用原生js实现一个函数,给页面制定的任意一个元素添加一个透明遮罩(透明度可变,默认0.2),使这个区域点击无效,要求兼容IE8+及各主流浏览器,遮罩层效果如下图所示:

<style>
#target {
width: 200px;
height: 300px;
margin: 40px;
background-color: tomato;
}
</style>
<div></div>
<script>
function addMask(elem, opacity) {
opacity = opacity || 0.2;
var rect = elem.getBoundingClientRect();
var style = getComputedStyle(elem, null);
var mask = document.createElement('div');
mask.style.position = 'absolute';
var marginLeft = parseFloat(style.marginLeft);
mask.style.left = (elem.offsetLeft - marginLeft) + 'px';
var marginTop = parseFloat(style.marginTop);
mask.style.top = (elem.offsetTop - marginTop) + 'px';
mask.style.zIndex = 9999;
mask.style.opacity = '' + opacity;
mask.style.backgroundColor = '#000';
mask.style.width = (parseFloat(style.marginLeft) +
parseFloat(style.marginRight) + rect.width) + 'px';
mask.style.height = (parseFloat(style.marginTop) +
parseFloat(style.marginBottom) + rect.height) + 'px';
elem.parentNode.appendChild(mask);
}
var target = document.getElementById('target');
addMask(target);
target.addEventListener('click', function () {
console.log('click');
}, false);
</script>
请用代码写出(今天是星期x)其中x表示当天是星期几,如果当天是星期一,输出应该是"今天是星期一"
var days = ['日','一','二','三','四','五','六'];
var date = new Date();
console.log('今天是星期' + days[date.getDay()]);
下面这段代码想要循环延时输出结果0 1 2 3 4,请问输出结果是否正确,如果不正确,请说明为什么,并修改循环内的代码使其输出正确结果
for (var i = 0; i < 5; ++i) {
setTimeout(function () {
console.log(i + ' ');
}, 100);
}
不能输出正确结果,因为循环中setTimeout接受的参数函数通过闭包访问变量i。javascript运行环境为单线程,setTimeout注册的函数需要等待线程空闲才能执行,此时for循环已经结束,i值为5.五个定时输出都是5 修改方法:将setTimeout放在函数立即调用表达式中,将i值作为参数传递给包裹函数,创建新闭包
for (var i = 0; i < 5; ++i) {
(function (i) {
setTimeout(function () {
console.log(i + ' ');
}, 100);
}(i));
}
现有一个Page类,其原型对象上有许多以post开头的方法(如postMsg);另有一拦截函数chekc,只返回ture或false.请设计一个函数,该函数应批量改造原Page的postXXX方法,在保留其原有功能的同时,为每个postXXX方法增加拦截验证功能,当chekc返回true时继续执行原postXXX方法,返回false时不再执行原postXXX方法
function Page() {}
Page.prototype = {
constructor: Page,
postA: function (a) {
console.log('a:' + a);
},
postB: function (b) {
console.log('b:' + b);
},
postC: function (c) {
console.log('c:' + c);
},
check: function () {
return Math.random() > 0.5;
}
}
function checkfy(obj) {
for (var key in obj) {
if (key.indexOf('post') === 0 && typeof obj[key] === 'function') {
(function (key) {
var fn = obj[key];
obj[key] = function () {
if (obj.check()) {
fn.apply(obj, arguments);
}
};
}(key));
}
}
} // end checkfy()
checkfy(Page.prototype);
var obj = new Page();
obj.postA('checkfy');
obj.postB('checkfy');
obj.postC('checkfy');
完成下面的tool-tip

编写javascript深度克隆函数deepClone
function deepClone(obj) {
var _toString = Object.prototype.toString;
// null, undefined, non-object, function
if (!obj || typeof obj !== 'object') {
return obj;
}
// DOM Node
if (obj.nodeType && 'cloneNode' in obj) {
return obj.cloneNode(true);
}
// Date
if (_toString.call(obj) === '[object Date]') {
return new Date(obj.getTime());
}
// RegExp
if (_toString.call(obj) === '[object RegExp]') {
var flags = [];
if (obj.global) { flags.push('g'); }
if (obj.multiline) { flags.push('m'); }
if (obj.ignoreCase) { flags.push('i'); }
return new RegExp(obj.source, flags.join(''));
}
var result = Array.isArray(obj) ? [] :
obj.constructor ? new obj.constructor() : {};
for (var key in obj ) {
result[key] = deepClone(obj[key]);
}
return result;
}
function A() {
this.a = a;
}
var a = {
name: 'qiu',
birth: new Date(),
pattern: /qiu/gim,
container: document.body,
hobbys: ['book', new Date(), /aaa/gim, 111]
};
var c = new A();
var b = deepClone(c);
console.log(c.a === b.a);
console.log(c, b);
补充代码,鼠标单击Button1后将Button1移动到Button2的后面
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>TEst</title>
</head>
<body>
<div>
<input type="button" id ="button1" value="1" />
<input type="button" id ="button2" value="2" />
</div>
<script type="text/javascript">
var btn1 = document.getElementById('button1');
var btn2 = document.getElementById('button2');
addListener(btn1, 'click', function (event) {
btn1.parentNode.insertBefore(btn2, btn1);
});
function addListener(elem, type, handler) {
if (elem.addEventListener) {
elem.addEventListener(type, handler, false);
return handler;
} else if (elem.attachEvent) {
function wrapper() {
var event = window.event;
event.target = event.srcElement;
handler.call(elem, event);
}
elem.attachEvent('on' + type, wrapper);
return wrapper;
}
}
</script>
</body>
</html>
网页中实现一个计算当年还剩多少时间的倒数计时程序,要求网页上实时动态显示"××年还剩××天××时××分××秒"
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>TEst</title>
</head>
<body>
<span></span>
<script type="text/javascript">
// 为了简化。每月默认30天
function getTimeString() {
var start = new Date();
var end = new Date(start.getFullYear() + 1, 0, 1);
var elapse = Math.floor((end - start) / 1000);
var seconds = elapse % 60 ;
var minutes = Math.floor(elapse / 60) % 60;
var hours = Math.floor(elapse / (60 * 60)) % 24;
var days = Math.floor(elapse / (60 * 60 * 24)) % 30;
var months = Math.floor(elapse / (60 * 60 * 24 * 30)) % 12;
var years = Math.floor(elapse / (60 * 60 * 24 * 30 * 12));
return start.getFullYear() + '年还剩' + years + '年' + months + '月' + days + '日'
+ hours + '小时' + minutes + '分' + seconds + '秒';
}
function domText(elem, text) {
if (text == undefined) {
if (elem.textContent) {
return elem.textContent;
} else if (elem.innerText) {
return elem.innerText;
}
} else {
if (elem.textContent) {
elem.textContent = text;
} else if (elem.innerText) {
elem.innerText = text;
} else {
elem.innerHTML = text;
}
}
}
var target = document.getElementById('target');
setInterval(function () {
domText(target, getTimeString());
}, 1000)
</script>
</body>
</html>
完成一个函数,接受数组作为参数,数组元素为整数或者数组,数组元素包含整数或数组,函数返回扁平化后的数组