一、 笔试真题
例:
<script>
var x = 1,
y = z = 0;
function add(n) {
return n = n + 1;
}
y = add(x);
function add(n) {
return n = n + 3;
}
z = add(x);
</script>
1,4,4,
同一个函数,后面会覆盖前面的,fn add 会提升到前面
例:下面代码中 console.log 的结果是[1, 2, 3, 4, 5]的选项是:
<script>
A、
function foo(x) {
console.log(arguments)
return x
}
foo(1, 2, 3, 4, 5)
B、
function foo(x) {
console.log(arguments)
return x
}(1, 2, 3, 4, 5)
C、
(function foo(x) {
console.log(arguments)
return x
})(1, 2, 3, 4, 5)
D、
function foo() {
bar.apply(null, arguments);
}
function bar(x) {
console.log(arguments);
}
foo(1, 2, 3, 4, 5);
</script>
答案
A, C,D 其中 b 执行不了,但是不报错
bar 里面传了一下参数。
bar .apply (null, arguments)== bar (arguments);
一行文本,水平垂直居中
height = line height
text-align:center
例:请问以下表达式的结果是什么?
<script>
parseInt(3, 8) //3
parseInt(3, 2) //NaN
parseInt(3, 0)//3
A .3, 3, 3
B .3, 3, NaN
C .3, NaN, NaN
D.other
</script>
答案 C 或 D(有的浏览器 0 进制报错,有的不报错)
parseInt() 函数
可解析一个字符串,并返回一个整数。
parseInt(要被解析的字符串, 要解析的数字的基数)
把当前数字(看第二个参数基底)返回十进制
<script>
parseInt("11", 2); //返回 3 (2+1)
parseInt("17", 8); //返回 15 (8+7)
parseInt("1f", 16); //返回 31 (16+15(f是15))
</script>
进制
十六进制 0 1 2 3 4 5 6 7 8 9 a b c d e f
十六进制的中 10 是十进制的 16, 1f = 16 + 15
二进制中的 10 是十进制的 2,11 是十进制的 3
例:以下哪些是 JavaScript 语言 typeof 可能返回的结果
A.string
B.array
C.object
D.null
typeof 可判断六个基本类型
1、undefined
2、Number
3、Boolean
4、function
5、Object
6、String
例:JavaScript 的 call 和 apply 方法是做什么的,两者有什么区别?
都是改变this的指向
call是传参数
apply是传arguments数组
<script>
例: 看看下面 alert 的结果是什么?
function b(x, y, a) {
arguments[2] = 10;
alert(a);
}
b(1, 2, 3);
如果函数体改成下面, 结果又会是什么?
a = 10;
alert(arguments[2]);
</script>
答案两个都是 10
逗号操作符,(1,2),会看一眼 1,在看一眼 2,然后返回第二个,就是 2
<script>
var f = (
function f() {
return "2";
},
function g() {
return 2;
}
)();
typeof f;
</script>
<script>
var x = 1;
if (function f() {}) {
x += typeof f;
}
console.log(x); //1undefined
</script>
用括号把function f(){}转换成表达式,就被立即执行了,就找不到了
因为function f() {}肯定是true ,所有会执行 {},但typeof f中的f已经找不到了
用友笔试题
<script>
例: 以下哪些表达式的结果为true()
A: undefined == null//true
B: undefined === null//false
C: isNaN( "100")//false
D: parseInt(”1a“) == //1
</script>
isNaN( “100”)意思是这个经过number转换后是不是NaN
模仿系统内部实现isNaN函数
<script>
function isNaN(num) {
var ret = Number(num);
ret += "";
if (ret == "NaN") {
return true;
} else {
return false;
}
}
</script>
引用值比的是地址
二、this
1、函数预编译过程 this —> 指向window
<script>
function test(c) {
//var this=Object.create(test.prototype);
//{
//__proto__"test.prototype
//}
var a = 123;
function b() {}
}
AO {
arguments: [1],
this: window,
c: 1,
a: undefined,
b: function() {}
}
test(1);
new test();
</script>
前面的var this=Object.create(test.prototype);是最标准的写法
new test();就会让var this=Object.create(test.prototype);如果不new,this指向window
<script>
function test() {
console.log(this);
}
test();
</script>
2、全局作用域里this—>指向window
3、call/apply 可以改变函数运行时this指向
4、obj.func()
func()里面的this指向obj
<script>
var obj = {
a: function() {
console.log(this.name);
},
name: 'abc'
}
obj.a();
</script>
谁调用这个方法,这个方法里的this就是指向谁
三、红宝书中的this
this是一个特殊的对象,在标准函数和箭头函数中都有不同的行为
在标准函数中
this引用的是把函数当成方法调用的上下文对象
<script>
window.color = 'red';
let o = {
color: "blue"
};
function sayColor() {
console.log(this.color);
}
sayColor(); //red
o.sayColor = sayColor;
o.sayColor(); //blue
</script>
在箭头函数中
this引用的是定义箭头函数的上下文
<script>
window.color = 'red';
let o = {
color: "blue"
};
let sayColor = () => {
console.log(this.color);
}
sayColor(); //red
o.sayColor = sayColor;
o.sayColor(); //red
</script>
在事件回调或定时回调中调用某个函数时,this值指向的并非想要的对象。
此时将回调函数写成箭头函数就可以解决问题
这是因为箭头函数中的this会保留定义该函数时的上下文
<script>
function King() {
this.royaltyName = "gxw";
//this引用King的实例
setTimeout(() => console.log(this.royaltyName), 1000);
}
function Queen() {
this.royaltyName = "xxw";
//this引用window对象
setTimeout(function() {
console.log(this.royaltyName);
}, 1000);
}
new King(); //gxw
new Queen(); //undefined
</script>
函数名只是保存指针的变量。因此全局定义的sayColor函数和o.sayColor()是同一个函数,只不过执行的上下文不同
<script>
var name = "222";
var a = {
name: "111",
say: function() {
console.log(this.name);
}
}
var fun = a.say;
fun(); //222
a.say(); //111
var b = {
name: "333",
say: function(fun) {
fun();
}
}
b.say(a.say); //222
b.say = a.say;
b.say(); //333
</script>
<script>
a.say是function函数体
function(fun){
//this-->b
//console.log(this)-->b
fun();
}
fun()空执行,走预编译
在b.say(a.say)中
a.say当做参数传进来了
</script>
arguments
arguments.callee指向函数的引用(函数自己)
function.caller
<script>
function test() {
console.log(arguments.callee);
}
test();
</script>
<script>
function test() {
console.log(arguments.callee == test);
}
test();
</script>
例:我们要初始化数据,是100以内的阶乘,用立即执行函数
找到自己的引用来解决
<script>
var num = (function(n) {
if (n == 1) {
return 1;
}
return n * arguments.callee(n - 1);
}(10))
</script>
<script>
function test() {
console.log(arguments.callee);
function demo() {
console.log(arguments.callee);
}
demo();
}
test();
</script>
在哪个函数里面的arguments.callee就指代了哪个函数
<script>
function test() {
demo();
}
function demo() {
console.log(demo.caller);
}
test();
</script>
demo被调用的环境是test
所以这个caller指代的是test
<script>
var foo = "123";
function print() {
var foo = "4456";
this.foo = "789";
console.log(foo);
}
print();//4456
</script>
把上面这题变形
<script>
var foo = "123";
function print() {
this.foo = "789";
console.log(foo);
}
print();//789
</script>
答案打印789,要console.log(foo);是全局的foo,但是这里this.foo的this是指向全局window的,相当于就把外面的123改成了789
<script>
var foo = "123";
function print() {
//var this=Object.create(print.prototype)
this.foo = "789";
console.log(foo);
}
new print();
</script>
答案123,new了之后,隐式var
this=Object.create(print.prototype)这时候this.foo不再指向window,转而指向var this,所以打印的时候找不到789,就到全局找到123
<script>
var a = 5;
function test() {
a = 0;
alert(a);
alert(this.a);
var a;
alert(a);
}
</script>
答案:
运行test()是0,5,0【之前其中this.a指代的是window,所以是5】
运行new test()是0,undefined,0【因为this上没有a,所以打印undefined
在执行test()之前,AO被定义{a:undefined},执行之后,Ao被执行{a:0,this:window}
在执行new test()时会隐式的var this=Object.create(test.prototype)简化就是var this{ __proto__:test prototype}一个对象上面没有的属性,打印出来就是undefined
new test();执行的时候是AO是{a:0,this:{} }
<script>
function print() {
console.log(foo);
var foo = 2;
console.log(foo);
console.log(hello);
}
print();
</script>
答案:undefined,2,报错hello is no defined
因为hello没有被定义,所以报错
<script>
function print() {
var test;
test();
function test() {
console.log(1);
}
}
print(); //1
</script>
<script>
function print() {
var x = 1;
if (x == "1") console.log("One!");
if (x === "1") console.log("Two");
}
print(); //One!
</script>
<script>
function print() {
var marty = {
name: "marty",
printName: function() {
console.log(this.name);
}
}
var test1 = {
name: "test1"
};
var test2 = {
name: "test2"
};
var test3 = {
name: "test3"
};
test3.printName = marty.printName;
var printName2 = marty.printName.bind({
name: 123
});
marty.printName.call(test1);
marty.printName.apply(test2);
marty.printName();
printName2();
test3.printName();
}
print();
</script>
<script>
var bar = {
a: "002"
};
function print() {
bar.a = "a";
Object.prototype.b = "b";
return function inner() {
console.log(bar.a);
console.log(bar.b);
}
}
print()();
</script>
bar.a=“a”;
把{a:“002”}
变成
{a:“a”}
a,b其中print()()第一个括号返回的是一个函数,第二个再来函数执行