工作中积累的问题、知识点总结100题(0-20)

1.给定一个只包括'(',')','{','}','[',']'的字符串,判断字符串是否有效

  满足以下要求:

    左括号必须用相同类型的右括号闭合

    左括号必须以正确的顺序闭合

// 方法1
    fun(str) {
      let len = str.length;
      if (len % 2 != 0) return false;
      let arr = [];
      for (let i = 0; i < len; i++) {
        let ll = arr[arr.length - 1];
        switch (str[i]) {
          case '(': arr.push(str[i])
            break;
          case '[': arr.push(str[i])
            break;
          case '{': arr.push(str[i])
            break;
          case ')':
            if (ll == '(') arr.pop(); else return false
            break;
          case '}':
            if (ll == '{') arr.pop(); else return false
            break;
          case ']':
            if (ll == '[') arr.pop(); else return false
            break;
        }
      }
      return arr.length == 0
    }

 

// 方法2,其实和方法1是一样的,就是写法不一样
    fun(str) {
      let len = str.length;
      if (len % 2 != 0) return false;
      let arr = [];
      for (let i = 0; i < len; i++) {
        if (str[i] == '(' || str[i] == '[' || str[i] == '{') {
          arr.push(str[i])
        } else {
          if (str[i] == ')' && arr.pop() != '(') {
            return false
          }
          if (str[i] == '}' && arr.pop() != '{') {
            return false
          }
          if (str[i] == ']' && arr.pop() != '[') {
            return false
          }
        }
      }
      return arr.length == 0
    }

 

2.让蓝色div在红色div中垂直居中

/*方法1--通过 flex 布局实现*/
.parent {
  width: 200px;
  height: 200px;
  background-color: red;
  display: flex;
  justify-content: center;
  align-items: center;
  .children {
    width: 50px;
    height: 50px;
    background-color: #409EFF;
  }
}

 

/*方法2--通过 position 定位实现,局限性,必须要知道子元素的高宽*/
.parent {
  width: 200px;
  height: 200px;
  background-color: red;
  position: relative;
  .children {
    width: 50px;
    height: 50px;
    background-color: #409EFF;
    position: absolute;
    top: 50%;
    left: 50%;
    margin-top: -25px;
    margin-left: -25px;
  }
}

 

/*方法三、通过 transform 实现*/
.parent {
  width: 200px;
  height: 200px;
  background-color: red;
  position: relative;
  .children {
    width: 50px;
    height: 50px;
    background-color: #409EFF;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%,-50%);
  }
}

 

3.字符串反转

    fun(str){
      return str.split('').reverse().join('')
    }

 

  // 2
  fun(str) {
      let ar = str.split('');
      let newStr = [];
      ar.map((i, index) => {
        newStr.push(ar[ar.length - index - 1])
      })
      return newStr.join('')
    }

 

4.css画一个三角形

.children {
    width: 0px;
    height: 0px;
border: 10px solid transparent; border-left: 20px solid blue;
/* border-top: 10px solid transparent; border-bottom: 10px solid transparent; border-left: 10px solid blue;*/ }

 

5.ECMA中所有函数的参数都是按值传递的

  值传递:把把一个值类型(也叫基本类型)传递给另一个变量时,其实是分配了一块新的存储空间,因此就本题来说,在内部改变这个值时,其实在函数外部对这个值没有影响。

var bb = 1;
function aa(bb) {
    bb = 2;
    alert(bb);
};
aa(bb);
alert(bb);

函数体内,bb并没有使用var来定义,按理说这个bb在预处理的时候应该是window的属性。但在这里,函数声明的时候,带了一个参数bb,也就是相当于在函数体内声明了var bb。所以,函数里的bb就是函数活动对象的属性。所以函数执行时会输出2。函数执行完后,函数的活动对象被销毁,也就是局部的这个bb被删除了,执行流进入到window,再输出bb,值就是1了。输出2再输出1

 

6.

function Foo() {
    var i = 0;
    return function() {
        console.log(i++);
    }
}
 
var f1 = Foo(),
    f2 = Foo();
f1();// 0
f1();// 1
f2();// 0

  一般来说函数执行完后它的局部变量就会随着函数调用结束被销毁,但是此题foo函数返回了一个匿名函数的引用(即一个闭包),它可以访问到foo()被调用产生的环境,而局部变量i一直处在这个环境中,只要一个环境有可能被访问到,它就不会被销毁,所以说闭包有延续变量作用域的功能。

其实foo()返回的是一个匿名函数,所以f1,f2相当于指向了两个不同的函数对象,所以结果f2()为0

 

7.找出网页中 html 的标签,并去重

        [...new Set([...document.querySelectorAll('*')].map(i=>i.nodeName))]

 

8.考察 js 中 this 指向问题

var name = 222;
    var a = {
      name = 111,
      say: function () {
        console.log(this.name);
      }
    };
    
    var fun = a.say;
    fun();// 222 直接执行函数 fun()  是 fun.call(window) 的一个简写  所以这里执行 this 指向 window
    a.say();// 111 a.say() 是 a.say().call(a) 的一个简写,this 指向 a
    
    var b = {
      name: 333,
      say: function (fun) {
        fun();// 222 这里也是直接执行函数 相当于 fun.call(window)
      }
    }
    
    b.say(a.say);// 在函数内部是直接执行 fun() 
    b.say = a.say;// 这里把 b.say 改成了 a 对象中的 a.say() 即 b.say = function () {console.log(this.name)}
    b.say();// 333 相当于 b.say().call(b)

 

9.考察 js 函数作用域的预编译

function fn(a, c) {
      console.log(a); // function a() {}
      var a = 111;
      console.log(a); // 111
      console.log(c); // function c() {}
    
      function a() {} // 函数声明会预编译,直接赋值给函数体
    
      if (false) var d = 222;// 虽然没执行,也会变量提升,先声明
      console.log(d); // undefined
      console.log(b); // undefined
      var b = function () {}
    
      console.log(b);// function() {}
      function c(){} // 函数声明会预编译,直接赋值给函数体
    
      console.log(c);// function c() {}
    }
    
    fn(1, 3);

 

10.考察转换

var a = ??// a = 什么的时候下面会打印 1
if (a == 1 && a == 2 && a == 3) console.log(1);
// 如果是复杂类型 那么在做比较的时候 隐式的调用对象的 valueOf
var a = {
  i: 0,
  valueOf() {
    return ++a.i
  }
}
// 如果是复杂类型  那么在做比较的时候 隐式的调用对象的 valueOf

 

// 方法 2
var a = [1,2,3];
a.join = a.shift;
// 利用了 [1] == 1

 

11.原型与原型链

var F = function() {};
Object.prototype.a = function() {
  console.log(1);
};
Function.prototype.b = function(){
  console.log(2);
}
var f = new F();

F.a();
F.b();
f.a();
f.b();

  结果是 1、2、1、报错(Uncaught TypeError: f.b is not a function)

  F 是个构造函数,而 F 是构造函数 Function 的一个实例。因为 F instanceof Object === true、F instanceof Function === true,由此我们可以得出结论:F 是 Object 和 Function 两个的实例,即 F 能访问到 a,也能访问到 b,所以 F.a() 输出 1 ,F.b() 输出 2 

  对于 f,f 并不是 Function 的实例,因为它本身就不是构造函数,调用的是 Function 原型链上相关属性和方法了,之能访问到 Object 原型链。所以 f.a() 输出 1 ,f.b() 就报错了

  f.b() 查找路径:f 自身:没有--> f.__proto__(Object.prototype):没有--> f.__proto__.__proto__(Object.prototype.__proto__: null):招不到,报错

 

12.作用域(执行环境)

var result = []
var a = 3
var total = 0
function foo(a) { // a = 1
  var i = 0
  for (; i < 3; i++) {
    result[i] = function () {total += i * a; console.log(total)}
  }
}

foo(1)
result.forEach(i=>{i();}) // 3 6 9

 

13.作用域 this

var n = 2;
var obj = {
  n: 3,
  fn: (function(n) {
    n *= 2;
    this.n += 2;
    var n = 5;
    return function(m) {
      this.n *= 2
      console.log(m + (++n));
    }
  })(n)
}

var fnn = obj.fn;
fnn(3); // 9
obj.fn(3); // 10
console.log(n, obj.n); // 8  6

 

14.原型与原型链

function Foo() {
  getName = function() {
    console.log(1)
  }
  return this
}
Foo.getName = function() {
  console.log(2)
}
Foo.prototype.getName = function() {
  console.log(3)
}
var getName = function() {
  console.log(4)
}

function getName() {
  console.log(5)
}

Foo.getName();// 2 函数 Foo 的静态方法
getName();// 4 function 有提前声明的规则,声明后被 var getName = ... 覆盖,所以是 4
Foo().getName();// 1 Foo 的 return this 是 window,window.getName() 在 Foo() 里面被覆盖,则为 1
getName();// 1 同上
new Foo.getName();// 2 相当于 function a() {console.log(2)} new a()
// 3 先执行了 new Foo(),返回一个对象,这个对象的 getName 为 prototype 上的 getName,相当于 (new Foo()).getName()
new Foo().getName();

 

15.this 和 arguments 

var length = 10;
function fn() {
  console.log(this.length)
}
var obj = {
  length: 5,
  method: function(fn) {
    fn();// 10
    arguments[0]()// 1 
    // 为什么这里是 1 ??? arguments也是对象,fn 也属于 arguments 数组中的一员,即当作为 arguments 成员之一调用的时候,
    // 它的作用域就绑定到了 argument 上,this 也就是指向了 arguments 对象,所以 arguments[0]() 这段代码调用了身为成员的 fn() 函数,
    // this.length就等于是 arguments.length ,参数为 1 个,所以最后输出 1
  }
}

obj.method(fn)

 

16.闭包与异步

   let i;
    for (i = 0; i < 3; i++) {
      let log = () => {
        console.log(i);
      };
      setTimeout(log, 200);
    }// 3  3  3

 

for (let i = 0; i < 3; i++) {
      let log = () => {
        console.log(i);
      };
      setTimeout(log, 200);
    }// 0  1  2

 

17.Object 和 Function 的关系

  Object 和 Function 都作为JS的自带函数,Object继承自己,Function继承自己,Object 和 Function 互相继承对方,也就是说Object 和 Funtion 都既是函数也是对象。

Function instanceof Object // true
Object instanceof Function // true 

  Object 是 Function 的实例,而 Function 是它自己的实例

 

18.自定义对象,prototype 原型属性

  使用 Object 函数创建对象,javascript 默认创建了一个 function Object(){}

    var p = new Object()
        p.name = 'zhangning'

  使用字面量的方式创建

var p = {name: 'zhangning'}

  prototype 注意细节:

    1)prototype 是函数(function)的一个必备属性(书面说法是’保留属性‘)(只要是function,就一定有一个 prototype 属性)

    2)prototype 的值是一个对象

    3)可以任意修改函数的 prototype 属性的值

    4)一个对象会自动拥有 prototype 的所有成员属性和方法

 

19.点运算符优先级

  3.toString()

  3..toString()

  3...toString()

  // 报错  '3'  报错

解析:    
    3.toString() 会被JS引擎解析成 (3.)toString() 报错     3..toString() 会被JS引擎解析成 (3.).toString() '3'     3...toString() 会被JS引擎解析成 (3.)..toString() 报错

 

20. 考察 . 和 = 操作符优先级

    let a = {n : 1};
    let b = a;
    a.x = a = {n: 2};
        
    console.log(a.x)
    console.log(b.x)

 

  答案:

    undefined

    {n: 2}

    js中.操作符的优先级大于=,先执行

 

posted @ 2021-03-25 14:05  张_Ning  阅读(122)  评论(0编辑  收藏  举报