声明:以下所有题从视频中人肉搬出来的,原视频连接
珠峰培训,对于Js 中的函数,原型,闭包,通过堆栈内存的画图分析,可以让你对Js有更深的了解. 本人也感谢视频作者 ,
答案在这里
下边有很多都是选择题, 有选项没啥意思, 直接上题了.
1: 写出结果:
console.log(a);
var a = 12;
function fn(){
console.log(a);
var a = 13;
}
fn();
console.log(a);
2: 写出结果:
console.log(a);
var a = 12;
function fn(){
console.log(a);
a = 13;
}
fn();
console.log(a);
3: 写出结果:
console.log(a);
a = 12;
function fn(){
console.log(a);
a = 13;
}
fn();
console.log(a);
4: 写出结果
var foo = 1;
function bar(){
if(!foo){
var foo = 10;
}
console.log(foo);
}
bar();
5: 写出结果
var n = 0 ;
function a(){
var n = 10;
function b(){
n++;
console.log(n)
}
b();
return b;
}
var c = a();
c();
console.log(n);
6: 写出结果
var a = 10 ,b = 11,c=12;
function test(a){
a = 1;
var b= 2;
c = 3;
}
test(10);
console.log(a);
console.log(b);
console.log(c);
7: 写出结果
if(!("a" in window)){
var a = 1;
}
console.log(a);
8: 写出结果:
function b(x,y,a) {
console.log(a);
arguments[2] =10;
console.log(a)
}
a = b(1,2,3);
console.log(a);
8.1 :写出结果:
function fn(x,y){
var arg = arguments;
arg[0] = 100;
console.log(x);
y = 200;
console.log(arg[1]);
}
fn(10);
8.2 :写出结果:
function fn(x,y){
var arg = arguments;
y = 200;
console.log(arg[1]);
arg[1] = 300;
console.log(y);
console.log(arguments[1]);
}
fn(10);
8.3 : 写出结果:
~function(){
var a = 1;
var a = 2;
console.log(a);
var b= {
n :10,
n :20
}
console.log(b.n);
(function(){
console.log(this);
})()
}();
8.4 : 写出结果:
~function(){
"use strict";
var a = 1;
var a = 2;
console.log(a);
var b= {
n :10,
n :20
}
console.log(b.n);
(function(){
console.log(this);
})()
}();
9: 写出结果:
var foo = 'hello';
(function(foo){
console.log(foo);
var foo =foo || 'world';
console.log(foo);
})(foo);
console.log(foo)
function fn(x = 0){
console.log(arguments);
console.log(x);
}
fn(null);
10: 写出结果:
var a = 9 ;
function fn(){
a = 0 ;
return function(b){
return b + a++;
}
}
var f = fn();
console.log(f(5));
console.log(fn()(5));
console.log(f(5));
console.log(a);
11: 写出结果:
var arr = [1,2,3,4];
function fn(arr){
arr[0] = 0;
arr= [0];
arr[0] = 100;
return arr;
}
var res = fn(arr);
console.log(arr);
console.log(res);
12: 写出结果:
function fn(i) {
return function(n){
console.log(n + ( i++));
}
}
var f = fn(10);
f(20);
fn(20)(40);
fn(30)(50);
f(30);
13: 写出结果:
var i = 10;
function fn(){
return function(n){
console.log(n + (++i));
}
}
var f = fn();
f(20);
fn()(20);
fn()(30);
f(30);
14: 写出结果:
var num = 10;
var obj = {num:20};
obj.fn = (function(num){
this.num = num * 3;
num ++;//
return function (n){
this.num += n;
num++;
console.log(num);
}
})(obj.num);
var fn = obj.fn;
fn(5);
obj.fn(10);
console.log(num);
console.log(obj.num);
15: 写出结果:
var num = 10;
var obj = {num: 20};
obj.fn = (function(num){
num = this.num +10;
this.num = num + 10;
return function(){
this.num += ++num;
}
})(num);
var fn = obj.fn;
fn();
obj.fn();
console.log(num);
console.log(obj.num);
16: 写出结果:
function Fn(){
this.x = 100;
this.y = 200;
this.getX = function(){
console.log(this.x);
}
}
Fn.prototype.getX = function(){
console.log(this.x);
}
Fn.prototype.getY = function(){
console.log(this.y);
}
var f1 = new Fn;
var f2 = new Fn;
console.log(f1.getX === f2.getX);
console.log(f1.getY === f2.getY);
console.log(f1.__proto__.getY === Fn.prototype.getY);
console.log(f1.__proto__.getX === f2.getX);
console.log(f1.getX === Fn.prototype.getX);
console.log(f1.constructor);
console.log(Fn.prototype.__proto__.constructor);
f1.getX();
f1.__proto__.getX();
f2.getY();
Fn.prototype.getY();
console.log(Fn.prototype);
console.log(f1.__proto__);
console.log(Fn.prototype === f1.__proto__);
17: DOM 元素绑定事件:点击一个按钮然后打印出当前的index
verson1 : 为什么不行 ?
var buttons = document.getElementsByTagName("button");
for(var i =0 ;i< buttons.length; i++){
buttons[i].onclick = function(){
console.log(i+1);
}
}
为啥不行? 事件绑定是异步编程 ,当触发点击行为,绑定的方法执行的时候,外层循环已经结束.
方法执行产生私有作用域,用到变量i,不是私有变量,按照作用域链的查找机制,找到的是全局下的i 这时候已经成为5
如何解决?
verson2 : 自定义属性
var buttons = document.getElementsByTagName("button");
for(var i =0 ;i< buttons.length; i++){
buttons[i].index = i+ 1;
buttons[i].onclick = function(){
console.log(this.index);
}
}
verson3 : --闭包
var buttons = document.getElementsByTagName("button");
for(var i =0 ;i< buttons.length; i++){
buttons[i].onclick = (function(i){
return function(){
console.log(i);
}
})(i);
}
每一轮循环都执行自执行函数形成私有作用域,里边设定一个私有变量i 让i 存储后期用到的索引.
点击触发方法执行,用到变量i,向对应上级作用域(没有销毁的那个)查找,而上级作用域中存储的i 的值就是我们需要的索引.
基于闭包解决非常消耗内存
version4: ES6
---ES6和闭包的机制类似, ES6中使用let 创建变量,会形成块级作用域,
当前案例中,每一轮循环都会有一个自己的块级作用域,把后续需要的索引i 实现存储到自己的作用域中
var buttons = document.getElementsByTagName("button");
for(let i =0 ;i< buttons.length; i++){
buttons[i].onclick = function(){
console.log(i+1);
}
}
18: 写出结果:用友面试题
var fullName = 'language';
var obj = {
fullName : 'javascript',
prop:{
getFullName : function(){
return this.fullName;
}
}
}
console.log(obj.prop.getFullName());
var test = obj.prop.getFullName;
console.log(test());
19: 写出结果
var name = 'window';
var Tom = {
name:"Tom",
show: function(){
console.log(this.name);
},
wait: function(){
var fun = this.show;
fun();
}
};
Tom.wait();
20: 写出结果
function fun(){
this.a = 0 ;
this.b = function(){
alert(this.a);
}
}
fun.prototype= {
b:function(){
this.a = 20;
alert(this.a);
},
c:function(){
this.a = 30;
alert(this.a);
}
}
var my_fun = new fun();
my_fun.b();
my_fun.c();
在实际项目基于面向对象开发的时候(构造原型设计模式),我们根据需要,很多时候会重定向累的原型,(让类的原型指向自己开辟的堆内存)
[存在的问题]
- 自己开辟的堆内存中没有constructor 属性,导致类的原型构造函数缺失,节点: 自己手动在堆内存中添加constructor属性
2:当原型重定向后,浏览器默认开辟的那个原型堆内存会被释放掉,如果之前已经存储了一些方法或者属性,这些东西都会丢失(所以内置类的原型
不允许重定向到自己开辟的堆内存,因为内置类原型上自带很多属性方法, 重定向之后都没了, 这样是不允许的)
内置类有自我保护的行为,就算用户修改了内置类的原型指向,但是浏览器中还是按照默认的来走.
当我们需要给类的原型批量设置属性和方法的时候,一般让原型重定向到自己创建的对象当中
20.1看看这个结果是多少 ?
function fn(){
}
var f1= new fn();
var f2 = new fn();
fn.prototype.a = 10;
console.log(f1.a);
console.log(f2.a);
f1.__proto__.a = 11;
console.log(f1.a);
console.log(f2.a);
21:
function Fn(){
var n = 10;
this.m = 20;
this.aa = function(){
console.log(this.m);
}
}
Fn.prototype.bb = function(){
console.log(this.n);
}
var f1= new Fn();
Fn.prototype = {
aa:function(){
console.log(this.m +10);
}
}
var f2 = new Fn();
console.log(f1.constructor);
console.log(f2.constructor);
f1.bb();
f1.aa();
f2.bb();
f2.aa();
f2.__proto__.aa();
22: 如何实现数组去重
var ary = [1,2,3,1,2,3,1,2,3,56,4325,43,21,1,12,123,55,];
version1:
function unique(ary){
var obj = {};
for(var i= 0 ;i< ary.length ; i++){
if(obj.hasOwnProperty(ary[i])){
ary[i] = ary[ary.length-1];
ary.pop();
i--;
continue;
}else{
obj[ary[i]] = true;
}
}
obj = null;
return ary;
}
基于内置类的原型扩展方法,供他的实例调取使用.
1: 我们增加的方法最好设置"my"前缀,防止把内置方法重写
Array.prototype.myUnique = function myUnique(){
//方法中的this 一般都是当前类的实例,(也就是我们操作的数组)
var obj = {};
for(var i = 0 ; i< this.length; i++){
var item = this[i];
obj.hasOwnProperty(item) ?
(this[i] = this[this.length-1],this.pop(),i--): obj[item] = item;
}
obj = null;
return this;
}
;
console.log(ary.myUnique().sort(function(a,b){
return a- b;
}).pop());
ary.__proto__.myUnique() //IE中屏蔽了我们对__proto__的操作
Array.prototype.myUnique();
Number.prototype.plus = function(input){
return this + input;
}
Number.prototype.minus = function(input){
return this - input;
}
var res = n.plus(3).minus(2);
console.log(res);
23: document.parentNode 和 document.parentnode 的区别(腾讯)
24: 怎么规避多人开发函数重名的问题?(百度搜索)
25:JavaScript 如何实现面向对象中的继承? (百度移动)
26: 你理解的闭包作用是什么 ? 优缺点 ?(乐视 )