@fantaghiro
2014-11-21T11:13:13.000000Z
字数 9713
阅读 3256
学习笔记 js 前端 妙味课堂
题1:
(function(){return typeof arguments;})();
解析:
typeof一共返回六种类型:字符串、number、布尔值、object对象、undefined、function函数,所以2、3项就剔除了
arguments是一个实参的集合,它是一个对象。
题2:
var f = function g(){ return 23; };typeof g();
解析:
如果第一行中的g不写的话,那么就是一个函数赋给了一个变量,这叫作“函数表达式”。这里这个函数是有名字的,因此叫作“有名的函数表达式”。多了这个名字,这种写法就是不规范的。这个f是能够找到的,但是这个g()在有些浏览器下是找不到的。因此选第四项Error。
题3:
(function(x){delete x;return x;})(1);
解析:
delete不能删除变量,也不能删除参数。它只能删除一个对象下面的属性。因此选第1项。
题4:
var y = 1, x = y = typeof x;x;
解析:
是从右向左执行的,那么在执行typeof x的时候,x还没有值的。所以typeof x返回的是"undefined"(typeof返回的都是字符串类型的)。这个字符串"undefined"又赋值给了y。这时候y就不是1了。然后再赋给x,x就是字符串"undefined"。
题5:
(function f(f){return typeof f();})(function(){ return 1; });
解析:
传入的参数f是匿名函数function(){return 1;},然后在自执行的函数里面f执行了(f()),所以这个f()就相当于1,那么typeof 1就是字符串的"number"
题6:
var foo = {bar: function(){ return this.baz; },baz: 1};(function(){return typeof arguments[0]();})(foo.bar)
解析:
foo.bar可以视为函数function(){ return this.baz; }的函数名,它通过arguments[0]传到自执行函数里面。也就是说foo.bar就是arguments[0],这个函数去执行,看起来这里的this是指向foo,其实不是。这个this要看从哪儿调用,它前面是谁。现在这个foo.bar看作一个整体,视为一个函数名,那么这个名为foo.bar的函数是在window下调用的,window下面没有baz,因此返回的应该是"undefined"。
题7:
var foo = {bar: function(){return this.baz;},baz: 1}typeof(f = foo.bar)();
解析:
这个题目跟上个题目差不多。也是将foo.bar作为一个整体赋给了f,那么f调用的时候,也还是在window下调用的。this指向是window,window下面没有baz,因此应选"undefined"。
题8:
var f = (function f(){return "1";},function g(){return 2;})();typeof f;
解析:
分组选择符:小括号。
var a = (1, 2, 3);alert(a); //弹出3 变量取得是最后一位
上面要走分组选择符后面的这个函数,后面函数return的是2,所以选择"number"
题9:
var x = 1;if(function f(){}){x += typeof f;}x;
解析:
函数声明是不能写到运算符的运算过程当中,例如if的括号或者for循环的括号中。函数写到这里面的话,函数名字就找不到了。函数声明必须是全局的或局部的,不能写到运算当中。所以typeof后面的f是找不到的,因此typeof f返回的是"undefined"。另外一个问题,这个函数写到括号当中,是返回真的。应该选第三个。
题10:
var x = [typeof x, typeof y][1];typeof typeof x;
解析:
不管x是什么,typeof x返回的必然是字符串。因此typeof 字符串返回的是"string"
题11:
(function(foo){return typeof foo.bar;})({foo: {bar: 1}});
解析:
形参foo只的是{foo: {bar: 1}}这个整体。在typeof foo.bar;中的这个foo下面只有一个foo属性,并没有bar这个属性,因此应该选"undefined"
题12:
(function f(){function f(){return 1;}return f();function f(){return 2;}})()
解析:
函数声明是会预解析的,因此在return f();这一句还没有执行的时候,上面和下面的这两句就已经执行完毕了。后面把前面的覆盖了,因此在return f();这一句执行的时候,这个f已经是下面的那个函数了。因此应该选择“2”。
题13:
function f(){return f;}new f() instanceof f;
解析:
instanceof方法是看前面的对象是否是后面的构造函数构造出来的。在构造函数中如果return了函数或者对象的话,那么这个函数或者对象就会把这个构造函数生成的对象覆盖掉。就相当于new f()执行完之后,就不是原本构造出来的对象了,而是f这个函数。f instanceof f返回的是false。
题14:
with (function(x, undefined){}) length;
解析:
函数的长度就是函数的形参数量。选择第二项:2。
function test(num1, num2, num3){}alert(test.length); //弹出3
1)外层的变量,内层可以找到(全局);内层的变量,外层找不到(局部)
//内部的可以调到外部的var a = 10;function aaa(){alert(a);}aaa(); //10
//外部的调不到内部的function aaa(){var a = 10;}aaa();alert(a); //报错
var a = 10;function aaa(){alert(a);}function bbb(){var a = 20;aaa();}bbb(); //弹出的是10
2) 当var不加的时候,会自动生成全局的变量(不建议这样写,最好把所有要定义的变量加上var)
function aaa(){a = 10;}aaa();alert(a); //10
function aaa(){var a = b = 10;}aaa();alert(a); //a找不到alert(b); //弹出10
3)变量的查找是就近原则去寻找var定义的变量。当就近没有找到的话,就会查找外层。
var a = 10;function aaa(){var a = 20;alert(a);}aaa(); //弹出20,因为在内层就找到a了
var a = 10;function aaa(){a = 20;alert(a);}aaa(); //弹出20。在内层没有找到var定义的a,会去找到外层的a,找到外层a之后,在内层,变量a的值先又变成了20,所以弹出的就是20。
var a = 10;function aaa(){alert(a);a = 20;}aaa(); //弹出10
var a = 10;function aaa(){alert(a);var a = 20;}aaa(); //undefined 在内层找到了var定义的a,因此就不会再找外层的var a = 10了。但是在内层找到了a,在alert(a)的时候,a还没有赋值20,因此就是undefined。
//上面的代码其实相当于这段代码://预解析原理var a = 10;function aaa(){var a;alert(a);a = 20;}aaa(); //undefined
var a = 10;function aaa(){bbb();alert(a);function bbb(){var a = 20;}}}aaa(); //10 函数bbb里面定义的局部变量a,在alert的时候是找不到的,alert的时候找的a是外层的var a = 10
4)当参数跟局部变量重名的时候,优先级是等同的。
var a = 10;function aaa(a){alert(a);var a = 20;}aaa(a); //10
var a = 5;var b = a;b += 3;alert(a); //5 基本类型的赋值,只存在一个值的关系,不存在引用的关系。
var a = [1, 2, 3];var b = a;b.push(4);alert(a); //[1, 2, 3, 4]; //对象之间是一种引用关系
var a = [1, 2, 3];var b = a;b = [1, 2, 3, 4];alert(a); //[1, 2, 3] b是重新赋值的,与a之间的联系就断开了。a、b之间就不存在什么关系了
var a = 10;function aaa(a){a += 3;}aaa(a);alert(a); //10 当我们传参进来之后,就相当于是重新赋值了,a是个基本类型,它+=3是不会影响到外部的这个变量a的。外面alert(a)中的a还是var a = 10这个a。alert(a)这里的a根本找不到aaa函数里面的a,因为函数的参数和局部变量的概念是一样的。
var a = [1, 2, 3];function aaa(a){a.push(4);}aaa(a);alert(a); //[1, 2, 3, 4] 函数aaa里面的参数a虽然与外面的a没有什么关系,但是因为这两者之间是一个引用关系,对局部的a进行push,也就相当于改了外边的a的引用,因此alert(a)的时候这个a还是外面的a,但是外面的a已经变成[1, 2, 3, 4]了。
var a = [1, 2, 3];function aaa(a){a = [1, 2, 3, 4];}aaa(a);alert(a); // [1, 2, 3] 里面的参数a是重新赋值了,而不是与外面的a存在引用关系。里面的a与外面的a没有任何关系了。alert(a)这里的a是外面的a,外面的a没变,还是[1, 2, 3]
题1:写一个字符串转成驼峰的方法
例如:border-bottom-color => borderBottomColor
方法一:字符串操作
var str = 'border-bottom-color';function test(str){var arr = str.split('-'); //[border, bottom, color]for(var i=1; i < arr.length; i++){arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].substring(1); //[border, Bottom, Color]}return arr.join('');}alert(test(str)); //borderBottomColor
方法二:正则操作
var str = 'border-bottom-color';function test(){var re = /-(\w)/g;return str.replace(re, function($0, $1){return $1.toUpperCase();});}alert(test(str));
题2:查找字符串中出现最多的字符和个数
例如:sdjksfssscfssdd => 字符最多的是s,出现了7次
方法一:字符串操作
var str = sdjksfssscfssdd;function test(str){var obj = {};var num = 0;var value = '';for(var i=0; i<str.length; i++){if( !obj[ str[i] ] ){obj[ str[i] ] = [];}obj[ str[i] ].push( str[i] );}for (var attr in obj){if(num < obj[attr].length){num = obj[attr].length;value = obj[attr][0];}}return '最多的字符是:' + value + ',出现了:' + num;}alert(test(str));
方法二:正则操作
var str = sdjksfssscfssdd;function test(str){var arr = str.split('');arr.sort();str = arr.join('');var re = /(\w)\1+/g;var num = 0;var value = 0;str.replace(re, function($0, $1){if(num < $0.length){num = $0.length;value = $1;}})return '最多的字符是:' + value + ',出现了:' + num;}alert(test(str));
题3:如何给字符串加千分符
例如:3562123761 => 3,562,123,761
方法一:字符串操作
var str = '3562123761';function test(str){var iNum = str.length%3;var prev = '';var arr = [];var iNow = 0;var tmp = '';if(iNum != 0){prev = str.substring(0, iNum);arr.push(prev);}str = str.substring(iNum);for(var i=0; i<str.length; i++){iNow++;tmp += str[i];if(iNow==3 && tmp){arr.push(tmp);tmp = '';iNow = 0;}}return arr.join(',');}alert(test(str));
方法二:正则操作
//正则语法://(?=) : 前向声明//(?!) : 反前向声明var str = 'abacad';var re = /a(?=b)/g; //用前向声明,只有a后面是b的时候,这个a才被匹配到,而b不是被匹配的内容str = str.replace(re, '*');alert(str); //'*bacad'
var str = 'abacad';var re = /a(?!b)/g; //用反前向声明,只有a后面不是b的时候,这个a才能被匹配到str = str.replace(re, '*');alert(str); //'ab*c*d'
var str = '3562123761';function test(str){var re = /(?=(?!\b)(\d{3})+$)/g; //这里从后往前,匹配到三位三位的位置,而且匹配上的这个位置前面不是独立部分。这个是什么意思呢,就是说如果数字正好是三个倍数位,例如123456,不添加这个(?!\b),得到的结果是',123,456'。但是添加上这个反前向声明,123前面的这个位置就不会被匹配上了。return str.replace(re, ',');}alert(test(str));
练习:返回一个只包含数字类型的一个数组?
例如:js123ldka78sdassdfd653 -> [123, 78, 653]
题目一:a b 两个变量 不用第三个变量来切换两个变量值
/* 适用性不广var a = 5;var b = 6;a = a + b;b = a - b;a = a - b;alert(a); //6alert(b); //5*/var a = 'hello';var b = 'hi';a = [a, b];b = a[0];a = a[1];alert(a); //'hi'alert(b); //'hello'
题目二:有一个数n=5,不用for循环,怎么返回[1, 2, 3, 4, 5]这样一个数组
方法一
var n = 5;function show(n){//用什么可以替代循环呢?递归、定时器。但是定时器用不了,因为它是异步的。考虑用递归。var arr = [];return (function(){arr.unshift(n);n--;if(n!=0){arguments.callee();}return arr;})();}alert(show(n)); //[1, 2, 3, 4, 5]
方法二
var n = 5;function show(n){var arr = [];arr.length = n + 1; //数组arr变成 [, , , , ,]var str = arr.join('a'); //str -> 'aaaaa'var arr2 = [];str.replace(/a/g, function(){arr2.unshift(n--);})return arr2;}alert(show(n)); //[1, 2, 3, 4, 5]
题目三:一个数n,当n小于100就返回n,否则就返回100
不限定条件
var n = 50;function show(){if(n<100){return n;} else {return 100;}}alert(show(n)); //50
限定条件:不允许用if else
var n = 50;function show(){return n < 100 ? n : 100;}alert(show(n)); //50
限定条件:不允许用if else,也不允许用三目
var n = 50;function show(){switch(n<100){case true:return n;break;case false:return 100;break}}alert(show(n)); //50
**限定条件:不允许用if else,三目和switch*
var n = 50;function show(){return Math.min(n, 100);}alert(show(n)); //50
**限定条件:不允许用if else、三目、switch和Math.min()*
var n = 50;function show(){var arr = [n, 100];arr.sort(function(n1, n2){return n1 - n2;})return arr[0];}alert(show(n)); //50
**限定条件:不允许用if else、三目、switch、Math.min()、数组*
var n = 50;function show(){var m = '' + n; //n=150的话,m.length是3;n=50的话,m.length是2for(var i=2; i<m.length && n>0; i++){return 100;}return n;}alert(show(n)); //50
限定条件:不允许用if else、三目、switch、Math.min()、数组、循环(包括for、while、do while)
var n = 50;function show(){var json = {name: 'hello'};var m = n < 100 || json;for(var attr in m){return 100;}return n;}alert(show(n)); //50
限定条件:不允许用if else、三目、switch、Math.min()、数组、循环(包括for、while、do while)、{} for in
var n = 50;function show(){var m = n >= 100 && 100; //n为150,前面为真,m就为100;n为50,m就是falsereturn m = m || n; //如果n为150,m就是100,最终返回的就是100;如果n为50,m得false,返回时m就等于后面的n,所以就返回50}alert(show(n)); //50
题1:斐波那契数列:1、1、2、3、5、8、13、21
方法一
//递归的写法function aaa(n){if(n <= 2) {return 1;}return aaa(n-1) + aaa(n-2);}alert(aaa(8)); //21 返回斐波那契数列第8项的值
方法二
//通过迭代的方式//迭代就是开循环,三个数迭代一次;8个数迭代6次function aaa(n){var num1 = 1;var num2 = 1;var num3 = 0;for(var i=0; i <n-2; i++){num3 = num1 + num2;num1 = num2;num2 = num3;}return num3;}alert(aaa(8));
题2:数组排序
冒泡排序
//冒泡排序是两个两个进行比较function aaa(arr){for(var i=0; i<arr.length; i++){for(var j=0; j<arr.length-i; j++){toCon(j, j+1);}}function toCon(prev, next){var tmp = '';if(arr[prev] > arr[next]){tmp = arr[prev];arr[prev] = arr[next];arr[next] = tmp;}}return arr;}alert(aaa([4, 5, 1, 7, 2])); //[1, 2, 4, 5, 7]
简单选择排序
简单选择排序:找到最小值扔到数组一开始,从剩余的找到最小值,排到刚才那个的前面function aaa(arr){if(arr.length == 1){return arr;}var iMin = arr[0];var iIndex = 0;for(var i=0; i<arr.length; i++){if( arr[i] < iMin ){iMin = arr[i];iIndex = i;}}var prev = arr.splice(iIndex, 1); //把1剪切出来成了一个数组[1],arr现在就变成了[4,5,7,2] 后面递归就可以了。return prev.concat(aaa(arr));}alert(aaa([4, 5, 1, 7, 2]));
题3:数组去重
方法一
//找到一个不重复的,就扔到新数组里面,剩余的里面再找不重复的,再扔到新数组里面,以此类推,最后返回新数组。function aaa(){var result = [ arr[0] ];for(var i=1; i<arr.length; i++){if( toCon( arr[i] ) ){ //如果没有重复的result.push( arr[i] );}}function toCon(val){for(var i=0; i<result.length; i++){if( result[i] == val){return false;}}return true;}return result;}alert(aaa([5, 2, 7, 5, 1, 7, 5, 4])); //[5, 2, 7, 1, 4]
方法二
//利用json的key值的唯一性function aaa(){var result = [];var obj = {};for(var i=0; i<arr.length; i++){if(!obj[arr[i]]){result.push(arr[i]);obj[arr[i]] = 1;}}return result;}alert(aaa([5, 2, 7, 5, 1, 7, 5, 4]));