【ECMAScript】三目运算、对象克隆、浅拷贝、深拷贝

1. 三目元算符/三元运算符

  1. 简写

    var a = 5;
    if(a > 0) {
      console.log('大于0');
    } else {
      console.log('小于等于0');
    }
    
    三段式简写:
    
    a > 0 ? console.log('大于0') 
          : console.log('小于等于0');
    
  2. 运算结果赋值

    var a = 5,
        str = '';
    if(a > 0) {
      str = '大于0';
    } else {
      str = '小于等于0';
    }
    
    // 三目简写
    var str = a > 0 ? '大于0' // 三目运算自带 return 功能
                : '小于等于0'
    
  3. 加括号运算

    var a = 5,
        str = '';
    if(a > 0) {
      if(a > 3) {
        str = '大于3';
      } else {
        str = '小于等于3';
      }
    } else {
      str = '小于等于0';
    }
    
    // 三目
    str = a > 0 ? (
                    a > 3 ? '大于3'
                          : '小于等于3'
                  )
                 : '小于等于0'
    
  4. 面试题

    字符串比较大小,比较的是ASCII码,第一位比完再比第二位

    var str = 89 > 9 ? (
                          '89' > '9' ? '通过了'
                                     : '内层未通过'
                        )
                     : '外层未通过'
    

2. 对象 拷贝/复制/克隆 clone

2.1 浅拷贝

并没有把对象里的引用值给处理了,只处理了第一层的属性,并没有处理下面的引用值

Object.prototype.num = 1; // 所有的对象都会继承这个属性
var person1 = {
  name: '张三',
  age: 18,
  sex: 'male',
  height: 180,
  weight: 140,
  son: {
    first: 'Jenney',
    second: 'Lucy',
    third: 'Jone'
  }
}

var person2 = {};

// 方法1:浅拷贝 遍历赋值的方式
for(var key in person1) {
  person2[key] = person1[key];
}

person2.name = '李四';
person2.son.forth = 'Ben';
console.log(person1, person2); 

//------------------------------

var person2 = person1;
person2.name = '李四';

console.log(person1, person2); // 因为它们指向同一个存储空间

封装成 function

Object.prototype.num = 1;
var person1 = {
  name: '张三',
  age: 18,
  sex: 'male',
  height: 180,
  weight: 140,
  son: {
    first: 'Jenney',
    second: 'Lucy',
    third: 'Jone'
  }
}

var person2 = clone(person1);

person2.name = '李四';
person2.son.forth = 'Ben';
console.log(person1, person2); 

function clone(origin, target) {
  var tar = target || {};
  for(var key in origin) {
    if(origin.hasOwnProperty(key)) { // 剔除原型上的属性
      tar[key] = origin[key];
    }
  }
  return tar;
}

2.2 深拷贝

拷贝之后的值怎么修改都与之前的值无关

方法1

Object.prototype.num = 1; // 所有的对象都会继承这个属性
var person1 = {
  name: '张三',
  age: 18,
  sex: 'male',
  height: 180,
  weight: 140,
  children: {
    first: {
      name: 'Jenney',
      age: 12
    },
    second: {
      name: 'Lucy',
      age: 12
    },
    third: {
      name: 'Jone',
      age: 12
    }
  },
  car: ['Benz', 'Mazda']
}

// 深拷贝
var person2 = deepClone(person1);

person2.name = '李四';
person2.children.forth = {name: 'Ben', age: 8};
person2.children.first.age = 20;
person2.car.push('ttt');
console.log(person1, person2); 

function deepClone(origin, target){
  var target = target || {},
      toStr = Object.prototype.toString,
      arrType = '[object Array]';
  for(var key in origin){
    if(origin.hasOwnProperty(key)) {
      if(typeof(origin[key]) === 'object' && origin[key] !== null) {
        toStr.call(origin[key]) === arrType ? target[key] = []
                                            : target[key] = {};
        deepClone(origin[key], target[key]);
      } else {
        target[key] = origin[key];
      }
    }
  }
  return target;
}

方法2

JSON.parse(JSON.stringify(person1));

// 缺点:无法拷贝方法

3. 笔试题

  1. 打印内容?

    function test(){
      console.log(foo); // undefined
      var foo = 2;
      console.log(foo); // 2
      console.log(a); // 报错: a is not defined
    }
    
    test();
    
  2. 打印的内容?

    function a(){
      var test;
      test();
      function test(){
        console.log(1);
      }
    }
    a(); // 1
    
  3. 打印的内容?⭐

    var name = '222';
    var a = {
      name: '111',
      say: function(){
        console.log(this.name);
      }
    }
    var fun = a.say;
    // 上面这一句相当于 var fun = function(){console.log(this.name)}
    
    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
    
  4. 打印结果是什么?

    function test(){
      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;
      marty.printName.call(test1); // test1
      marty.printName.apply(test2); // test2
      marty.printName(); // marty
      test3.printName(); // test3
    }
    test()
    
  5. 打印结果是什么?

    var bar = {
      a: '1'
    }
    
    function test(){
      bar.a = 'a';
      Object.prototype.b = 'b';
      return function inner(){
        console.log(bar.a); // a
        console.log(bar.b); // b
      }
    }
    
    test()();
    

4. 作业

  1. 打印结果,并分析其原因

    function Foo(){
      getName = function(){ // 没有经过 var 的变量,提升到全局
        console.log(1);
      }
      return this;
    }
    
    Foo.getName = function(){
      console.log(2);
    }
    
    // 问:怎么样才能访问到原型上面?⭐
    // 答:构造函数 new 实例化了之后的对象并没有getName方法,才会访问到原型上面
    Foo.prototype.getName = function(){
      console.log(3);
    }
    
    var getName = function(){
      console.log(4);
    }
    
    function getName(){
      console.log(5);
    }
    
    Foo.getName(); // 2 Foo充当了一个对象,这里只是访问自己的一个属性
    getName(); // 4  GO = {getName => undefined -> function(){5} -> function(){4}}
    
    // 答案是1,为什么???
    Foo().getName(); // 1 Foo 中的 getName 提升到全局 ⭐
    getName(); // 1
    // . 运算的优先级比 new 运算的优先级高
    new Foo.getName(); // 2 先执行 Foo.getName,得到结果 2,new 一个数字没有意义
    // 括号的优先级比点大,括号先执行 ⭐
    // 如果前面有new,函数是一个执行体,new 是跟执行体一起走的 ⭐
    // 先执行new Foo(),然后在构造函数上找 getName,没找到,则去原型上找getName
    new Foo().getName(); // 3 
    // 先执行 new Foo(),然后执行原型上的 getName,得到3,这时再 new 一个数字没有意义
    new new Foo().getName(); // 3 
    
  2. 请用 window.prompt 接收用户输入的年份,判断是否是闰年?(用三目运算符做)

    闰年:整除4或400 并且不能整除100

    function isLeap(n){
      return (n % 4 === 0 && n % 100 !== 0) || n % 400 === 0 ? true : false;
    }
    
    console.log(isLeap(2020));
    console.log(isLeap(2021));
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值