四舍五入、prototype添加自定义方法
四舍五入后计算数组元素的总和:
向 Array 对象添加自定义方法
Array.prototype.average = function() {
// 计算 sum 的值
var sum = this.reduce(function(prev, cur) { return prev + cur; });
// 将 sum 除以元素个数并返回
return sum / this.length;
}
var arr = [1, 2, 3, 4, 5];
var avg = arr.average();
console.log(avg); // => 3
this”关键字的原理是什么?
难度星级: ****
在 JavaScript 中,this 是指正在执行的函数的“所有者”,或者更确切地说,指将当前函数作为方法的对象。
function foo() { console.log( this.bar ); } var bar = "global"; var obj1 = { bar: "obj1", foo: foo }; var obj2 = { bar: "obj2" }; foo(); // "global" obj1.foo(); // "obj1" foo.call( obj2 ); // "obj2" new foo(); // undefined
请解释原型设计模式。
难度星级: ****
原型模式可用于创建新对象,但它创建的不是非初始化的对象,而是使用原型对象(或样本对象)的值进行初始化的对象。原型模式也称为属性模式。
原型模式在初始化业务对象时非常有用,业务对象的值与数据库中的默认值相匹配。原型对象中的默认值被复制到新创建的业务对象中。
经典的编程语言很少使用原型模式,但作为原型语言的 JavaScript 在构造新对象及其原型时使用了这个模式。
Javascript 中的“闭包”是什么?举个例子?
难度星级: ****
闭包是在另一个函数(称为父函数)中定义的函数,并且可以访问在父函数作用域中声明和定义的变量。
闭包可以访问三个作用域中的变量:
- 在自己作用域中声明的变量;
- 在父函数中声明的变量;
- 在全局作用域中声明的变量
var globalVar = "abc";
// 自调用函数
(function outerFunction (outerArg) { // outerFunction 作用域开始
// 在 outerFunction 函数作用域中声明的变量
var outerFuncVar = 'x';
// 闭包自调用函数
(function innerFunction (innerArg) { // innerFunction 作用域开始
// 在 innerFunction 函数作用域中声明的变量
var innerFuncVar = "y";
console.log(
"outerArg = " + outerArg + "
" +
"outerFuncVar = " + outerFuncVar + "
" +
"innerArg = " + innerArg + "
" +
"innerFuncVar = " + innerFuncVar + "
" +
"globalVar = " + globalVar);
// innerFunction 作用域结束
})(5); // 将 5 作为参数
// outerFunction 作用域结束
})(7); // 将 7 作为参数
innerFunction 是在 outerFunction 中定义的闭包,可以访问在 outerFunction 作用域内声明和定义的所有变量。除此之外,闭包还可以访问在全局命名空间中声明的变量。
匿名和命名函数有什么区别?
注:函数表达式中的代理名称本来就是不必要的最终还是赋值给左边声明的变量
var foo = function() { // 赋给变量 foo 的匿名函数 // .. }; var x = function bar(){ // 赋给变量 x 的命名函数 bar // .. }; foo(); // 实际执行函数 x();
按照ECMAScript标准,函数表达式的样式如下(opt记号代表的是可选的,也就是可有可无的意思):
FunctionExpression :
function Identifier opt ( FormalParameterList opt ){ FunctionBody }
函式表达式中函数的识别名是可以不需要有的,有名称的函数表达式,也就是所谓的"具名函数表达式"(Named function expressions,NFE),这个函数的识别名,它的作用域是只能在函数的主体(FunctionBody)内部。原因当然它只是个原本就可有可无的"代理"函数名,真正的这函数识别名称是被赋值的那个变量识别名。
正常情况下,你只能在函数表述式中的主体中使用这个"代理函数名",这也是符合标准的规定,如下面的例子:
var f = function foo(){
return typeof foo;
};
typeof foo; // "undefined"
f(); // "function"
那么又为何要使用这个"代理函数名",不是可有可无的吗?
因为这个名称在调试时,可以明确地在调用栈中看到,如果是不加这名称,也就是"匿名函数表达式"在调试时是看不准是呼叫什么的。这使得调试时多了一些便利,所以它会被用在这个情况下。
但在IE8之前的IE版本,它对待这个"代理函数名",可以像一般的函数声明
一样。因为以IE8来说,它里面的JS引擎并不是现在的标准ECMAScript规定,而是JScript 5.8。
IE8并没有设计这个封闭作用域,来界定出函数表达式的作用域,而且,在IE8中认为这种有"具名函数表达式",相等于函数声明
。而且IE8还会认为这两个函数(被赋值的变量与这个代理名)是两个不同的函数物件,例如下面的例子:
var f = function foo(){
return 23;
}
alert(f === foo); //false
以上的资料主要参考Named function expressions demystified与Function Declarations vs. Function Expressions
function
foo(){
function
bar() {
return
3;
}
return
bar();
function
bar() {
return
8;
}
}
alert(foo());
//**Simulated processing sequence for Question 1**
function
foo(){
//define bar once
function
bar() {
return
3;
}
//redefine it
function
bar() {
return
8;
}
//return its invocation
return
bar();
//8
}
alert(foo());
1
|
var today = function today() { return new Date()} |
解释 JavaScript 中“undefined”和“not defined”之间的区别。
难度星级: ***
在 JavaScript 中,如果你试图使用一个不存在且尚未声明的变量,JavaScript 将抛出错误“var name is not defined”,让后脚本将停止运行。但如果你使用 typeof undeclared_variable,它将返回 undefined。
promise
promise 提供了一种机制来处理异步操作结果。你可以使用回调来达到同样的目的,但是 promise 通过方法链接和简洁的错误处理带来了更高的可读性。
function
foo(){
return
bar();
var
bar =
function
() {
return
3;
};
var
bar =
function
() {
return
8;
};
}
alert(foo());
//**Simulated processing sequence for Question 4**
function
foo(){
//a declaration for each function expression
var
bar = undefined;
var
bar = undefined;
return
bar();
//TypeError: "bar not defined"
//neither Function Expression is reached
}
alert(foo());
类定义和继承
ES6 引入了对类(关键字 class)、构造函数(关键字 constructor)和用于继承的 extend 关键字的支持。
新的 ES6 关键字 let 允许开发人员声明块级别作用域的变量。let 不像 var 那样可以进行提升。