零JS筆記 | 題目
1、typeof類型
(function () {
return typeof arguments;
})();
//argument实参集合,即对像,有数组的长度,也可for,但没有arr的方法;push unshift
var f = function g() {
return 23;
}
typeof g();
//有名函数表达式,不规范,不建议写,g()找不到的,在外部typeof 找不到的g(),其实是error
(function (x) {
delete x;
return x;
})(1)
//删除元素,不能删除变量也不能删除参数,只能删除一个对像下面的方法,所以删不掉,返回的还是1
var y = 1, x = y = typeof x;
x;
//从右往左运算; typeof 没有值,返回undefined; 注意;type返回字符串类型 所以是加了双引号的 "undefined"
(function f(f) {
return typeof f();
})(function () {
return 1;
})
//執行后返回1 typeof == 'number'
var foo = {
bar: function () {
return this.baz
},
baz: 1
};
//this指向哪?this不看在哪定义,关键看在哪执行;
(function () {
return typeof arguments[0]();
})(foo.bar);
// 正常来写,this肯定指向foo 但当一个整体当参数传进来时,this使用window调用,window下没有.baz,所以返回 'undefined'
var foo = {
bar: function () {
return this.baz
},
baz: 1
};
typeof (f = foo.bar)()
//this指向哪? this不看在哪定义,关键看在哪执行;还是指向window,所以是 'undefined'
var f = (function f() {
return '1'
}, function g() {
return 2;
})()
typeof f;
//分组选择,变量执行最后一位 var a = (1,2,3), alert(a) 3
var x = 1;
if (function f() {}) {
x += typeof f;
}
x;
//函数声明,写法是不允许的 ;写进去后名字f找不到了;肯定是返回 'undefined',但if是否会执行?
//但fn写在if里,确实返回真,所以会执行;1 + 'undefined' == '1undefined'
var x = [typeof x, typeof y][1];
typeof typeof x;
//x不需要看,没意义 ;
// 不管x = 什么,返回必然是字符串,typeof 字符串返回 string
(function (foo) {
return typeof foo.bar;
})({foo: {bar: 1}});
//整体下面只有一个foo,没有bar相當於: {foo:{bar:1}}).bar 所以是undefined
(function f() {
function f() {return 1}
return f(); //函數聲明會預解析,所以當到這裏時,f()覆蓋,已經是2
function f() {
return 2
}
})()
function f() {
return f; //本來是對的,但如果 return回同行函數,則會覆蓋,所以是false
}
new f() instanceof f; //instanceof前面是不是構造fn出來的,如果是返回true; new f() 執行完後其實是f,即 f instanceof f == false;
width(function (x, undefined) {
}).length; //函數的開度就是函數的形參; argument是實參集合
2、作用域
1)外層的變量內層可以找到,全局;內層的變量外層找不到,局布;
var a = 10 ;
function aaa(){
alert(a)
}
function bbb(){
var a = 20
aaa(); //這裏調用時並不是把aaa()函數拿進來,而是在外部找aaa()函數,所以是10
}
bbb();
function aaa(){
a = 10; //相當於在外面定義,所以可找a ,當 var 不加時全自動生成全局變量,(不建議使用;把有變量都定義為var
}
aaa()
alert(a)
function aaa(){
var a = b = 10; //這種寫法相當於 var a = 10; b= 10,即b不使用var聲明,所以b是全局;
}
aaa()
// alert(a);
alert(b);
var a = 10;
function aaa(){
alert(a); //undefined 第二步預解析時,有var,所以a = undefined; 之後a 在aaa()裏執行了,相當於aaa()類似於一個window的作用域那樣理解,裏面有var a了,所以a不會向外面找;
var a = 20
}
aaa()
3)、變量的查找;就近原則去尋找var 定義的變量;
var a = 10;
function aaa(){
alert(a); //10
a = 20
}
aaa()
var a = 10;
function aaa(){
a = 20
alert(a); //20
}
aaa()
var a = 10;
function aaa(){
alert(a);
var a = 20
}
aaa()
/* alert(a);
var a = 20
* =========== 相等於
* var a;
* alert(a);
* a = 20;
* 所以是undefined;
*
*/
var a = 10;
function aaa(){
bbb()
alert(a);
function bbb(){
var a = 20;
}
}
aaa() //10 aaa()裏的a找不到bbb()裏面的a
4)、當參數跟局布變量重名時,優先級等同
var a = 10;
function aaa(a){
alert(a);
var a = 20;
}
aaa(a) //10
var a = 5;
var b = a;
b += 3;
console.log(a); //普通變量不會影響到a,所以是5*/
//對像是引用關係 ;
var a = [1,2,3]
var b = a;
b.push(4)
console.log(a); //[1, 2, 3, 4]
var a = 10;
function aaa(a){
a += 3; //a重新給地址了;
}
aaa(a)
alert(a);
//10,當傳參數進後來後相當於重新賦值;因為a是基本類型,不是對象數組,所以裏面的改變不會影響 到a,參數跟局布變量概念一樣;
var a = [1,2,3];
function aaa(a){
a.push(4); //a是引用關係了,地址沒變;
}
aaa(a)
alert(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]
3、題形
寫一個字符串轉成駝鋒的方法;
解一:
var str = 'border-bottom-color'
function text(str) {
var arr = str.split('-');
for (var i = 1; i < arr.length; i++) {
arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
}
return arr.join('');
}
console.log(text(str));
解二:
var str = 'border-bottom-color'
function textZ(str){
/*找-字符 再用g全局匹配;*/
var re = /-(\w)/g;
return str.replace(re, function (_0,_1) {
/* 第一個整體,第二個代表子項 */
return _1.toUpperCase(); /*
注意:這裏 _0 == _B _C
_1 == B C
*/
})
}
console.log(textZ(str));
查找字符串中出現最多的字符及個數;
解一:
var str2 = 'asdlkfjasldkfjalksdjfkllkdkkaksldfkkkkkk'
function textC(){
/*通過json存*/
var obj = {}
var num = 0;
var value = '';
/*思路:
* obj = {
* a:[],
* b:[],
* c:[]
* }
*/
for (var i = 0; i < str2.length; i++) {
if ( !obj[ str2[i] ] ) { //當不存在時,即去掉重複添加;
obj[ str2[i] ] = []; //先創建空數組集合;
}
obj[ str2[i] ].push(str2[i]); //再把每一項push進創建的每個集合裏;
}
/*對比集合裏的項數;
* */
for (var attr in obj) {
if (num < obj[attr].length) {
/*這兩步只是num<obj[attr].length才會走這裏*/
num = obj[attr].length
/* num永遠是集合中最長的,理解下這裏*/
value = obj[attr][0];
}
}
return '最多是' + value + '一共有' + num + '個'
}
console.log(textC(str2));
解二:
var str3 = 'asdlkfjasldkfjalksdjfkllkdkkaksldfkkkkkk'
function testCZ(str3){
var arr3 = str3.split('');
arr3.sort();
str3 = arr3.join(''); //把相同的排在一起;再存
console.log('abc'+str3);
var re = /(\w)\1+/g; /* \1代表著跟第一個子項完全一樣的,即複製多個才匹配到,注意理解; + 表示可以出現多次,g表示多次匹配 */
var num3= 0; var value3 = 0;
str3.replace(re, function (_0,_1) {
if(num3<_0.length){
num3 = _0.length;
value3 = _1;
}
})
return '最多是' + value3 + '一共有' + num3 + '個'
}
console.log(testCZ(str3));
如何給字符串加千分符
解一:
var str4 = '12658656489' //[12,658,956,564,689]
function test4(str4) {
var inum = str4.length % 3;
var prev = '';
var arr = [];
var inow = 0; //三位三位計算
var tmp = ''
if (inum != 0) {
prev = str4.substring(0, inum);
arr.push(prev)
}
str4 = str4.substring(inum)
for (var i = 0; i < str4.length; i++) {
inow++
tmp += str4[i]
if (inow == 3 && tmp) {
arr.push(tmp);
tmp = '';
inow = 0;
}
}
return arr.join(',')
}
console.log(test4(str4));
解二:
var str5 = '126556489'
function testZ4(){
/*後面必須是三位數字*/
var re = /(?=(?!\b)(\d{3})+$)/g;
/*
* 寫一個前期聲明:(?=)
* 子項裏是數字(?=(\d))
* 聲明是3位 (?=(\d{3}))
* 3位最少出現1次,所以(?=(\d{3}+))
* 然後位置出現在後面結束位置(?=(\d{3}+$))
* 然後是全局:/(?=(\d{3})+$)/g bug:如果剛好是3位3位,則起始位置也會匹配到;
* 所以前項聲明前再來一個反前期聲明:/(?=(?!\b)(\d{3})+$)/g
* \b代表正則中的獨立部分;比如:開始,結束,空格,都是獨立部分,所以,不包超始位置加\b
* */
return str5.replace(re,',')
}
console.log(testZ4(str5));
前項聲明入 反前項聲明
(function () {
var s = 'abacad'
var re = /a(?=b)/g; //匹配 ab,但只替換匹配到的ab中的a,b不替換;
s = s.replace(re,'*')
console.log(s); //*bacad
})();
(function () {
var s = 'abacad'
var re = /a(?!b)/g; //匹配 ab,a後面不能匹配到b,其他可以匹配
s = s.replace(re,'*')
console.log(s); //ab*c*d
})()
把一個字符串中所有數字類型以數組存形輸出;
解一:
var str6 = 'js123kdslfkjd78klw0jfldjs966gg989dfsdf5'
function text6(str6) {
var arr = []
var tmp = ''
for (var i = 0; i < str6.length; i++) {
if (Number(str6[i]) || str6[i] == 0) {
tmp += str6[i]
}
else {
if (tmp) {
arr.push(tmp);
}
tmp = ''
}
}
arr.push(tmp) //修復最後一位是數字的情況;
return arr
}
console.log(text6(str6));
解二:
var str7 = 'js123kdslfkjd78klw0jfldjs966gg989dfsdf5'
function test7(str7){
var arr = []
str7 = str7.replace(/\d+/g, function (_0,_1) {
return arr.push(_0)
})
return arr;
}
console.log(test7(str7));
4、限制條件題 ;
ab兩變量,不用第3個變量來切換兩個變量值;
只適用數字:
var a = 5;
var b = 6;
a = a + b
b = a - b
a = a - b;
console.log(a); //6
console.log(b); //5
適用所有類型:
var a = 'hello'
var b = 'hi'
a = [a,b]
b=a[0] //順序不能換;
a=a[1]
console.log(a);
console.log(b);
有一個數n=5,不用循環,怎麼返回[1,2,3,4,5]這樣一個數組;
利用遞歸
var n = 5
function arrshow(n){
var arr = []
return (function k() {
arr.unshift(n)
n--;
if(n!=0){
//可直接使用下面,調用當前正被執行的對象,即()()裏的對象,所以不需要命名;
// arguments.callee()
k() //也可使用遞歸,但需要命名函數本身,即加k
}
return arr;
})()
}
console.log(arrshow(5));
利用replace
var n = 5;
function arrshow(n){
var arr = [];
arr.length = n+1; //[,,,,,]
var str = arr.join('a') //str = 'aaaaa'
var arr2 = []
str.replace(/a/g, function () {
arr2.unshift(n--)
})
return arr2
}
console.log(arrshow(5));
一個數n,當小於100返回n,否則返回100
n解:
var n = 50;
function shown(n){
return n < 100 ? n : 100;
}
console.log(shown(n));
/***********************************/
var n = 50;
function shown(n){
return Math.min(n,100)
}
console.log(shown(n));
/***********************************/
var n = 50;
function shown(n){
var arr = [n,100];
arr.sort(function (n1,n2) {
return n1 - n2
})
return arr[0]
}
console.log(shown(n));
/***********************************/
var n = 500;
function shown(n){
var m = ''+n
for(var i=2;i< m.length && n>0 ;i++){ //位數來判斷;
return 100
}
return n;
}
console.log(shown(n));
/***********************************/
var n = -500;
function shown(n){
var json = {name:'hello'}
var m = n<100 || json;
for(var attr in m){
return 100
}
return n;
}
console.log(shown(n));
/***********************************/
var n = 500;
function shown(n){
var m = n>=100 && 100
return m = m || n;
}
console.log(shown(n));
<h2>算法</h2>
斐波那契数列:前兩位相加等於第三位
遞歸:
function aaa(n){
if(n<=2){
return 1
}
return aaa(n - 1) + aaa(n - 2)
}
console.log(aaa(8)); //21
迭代:(開循環操作)
function bbb(n){
var num1 = 1; //第1
var num2 = 1; //第2
var num3 = 0;
for(var i=0;i<n-2;i++){
num3 = num1 + num2;
num1 = num2 //num1變後一個數
num2 = num3 //上一次num3的值
}
return num3;
}
console.log(bbb(8));
<h2>數組排序</h2>
快速排序
function qsort(arr){
if(arr.length<=1){
return arr;
}
var n = Math.floor(arr.length/2)
var nV = arr.splice(n,1)
var l = []
var r = []
for(var i=0;i<arr.length;i++){
if(arr[i]<nV){
l.push(arr[i]);
}
else{
r.push(arr[i])
}
}
return qsort(l).concat([nV],ccc(r))
}
alert(qsort([4, 5, 6, 3, 2, 10]))
冒泡排序
兩兩比較;嵌套2次循環
function msort(arr) {
for (var i = 0; i < arr.length; i++) {
for (var j = 0; j < arr.length - i; j++) {//每兩次,當第一輪找到一個數時,可去掉已找到的,即減i
toCon(i, i + 1)
}
}
function toCon(prev, next) {
var tmp = ''
if (arr[prev] > arr[next]) {
tmp = arr[prev]
arr[prev] = arr[next]
arr[next] = tmp;
}
}
return arr
}
console.log(msort([40, 5, 6, 3, 2, 10]));
简单选择排序:每一次找最小值,把最小值放在最前面;
function ssort(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位
return prev.concat(ssort(arr))
}
console.log(ssort([40, 5, 6, 3, 20, 10]));
<h2>数组去重</h2>
1
function dup(arr) {
var result =[ arr[0] ] ; //初始化给第一项,注意放在数组里
for (var i = 1; i < arr.length; i++) { //从第1个开始
if (toCon(arr[i])) { //封方法,返回真表示无重复
result.push(arr[i])
}
}
function toCon(v) {
for (var i = 0; i < result.length; i++) {
if (result[i] == v) {
return false
}
}
return true //不走if返回ture,上面可添加
}
return result
}
console.log(dup([32, 3, 4, 34, 5, 44, 3]));
2、利用obj属性
function jdup(arr) {
var result = []
var obj = {}
for (var i = 1; i < arr.length; i++) {
if (!obj[arr[i]]) {
result.push(arr[i])
obj[arr[i]] = 1; //让obj的32:1,所以obj = {32:1,3:1,4:1....}
}
}
return result
}
console.log(jdup([32, 3, 4, 34, 5, 44, 3, 55, 32]));