链式调用、对象属性与遍历、this指向、caller、callee
链式调用
let sched = {
wekeup: function () {
console.log("Running");
return this;
},
morning: function () {
console.log("Going shopping");
return this;
},
noon: function () {
console.log("Having a rest");
return this;
},
afternoon: function () {
console.log("Studying");
return this;
},
evening: function () {
console.log("Walking");
return this;
},
night: function () {
console.log("Sleeping");
return this;
},
};
sched.wakeup().morning().noon().afternoon().evening().night();
- 必须要返回这个对象本身才能链式调用对象的其他方法
字符串拼接
// 对象属性字符串拼接
let myLang = {
No1: "HTML",
No2: "CSS",
No3: "JavaScript",
myStudyingLang: function (num) {
// console.log(this.No + num) 这样打印不出来 因为this.No是undefined;
console.log(this["No" + num]); // 这样才能打印出来,字符串拼接属性名时只能这样写
},
};
myLang.myStudyingLang(1);
obj = {
name: "123",
};
console.log(obj["name"]);
// 这样也能访问对象的属性
// 因为js引擎会在你 obj.name 时 隐式转化成 obj['name']
对象枚举(遍历)
// 对象枚举
// 实际上是对象
// 枚举 -> 遍历
// 遍历是在一组信息内 一个一个按顺序获取信息的过程 就叫遍历
// 有枚举就有遍历
let arr = [1, 2, 3, 4, 5];
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
let car = {
brand: "Benz", // key : value
color: "red",
displacement: "3.0",
lang: "4",
width: "2.5",
};
for (let key in car) {
console.log(key); //打印键名
// console.log(car.key); 这样打印不出来value
// car.key -> car['key'] -> 找不到'key' 所以是undefined
console.log(key + ":" + car[key]);
}
let arr1 = [1, 2, 3, 4, 5];
for (let i in arr1) {
console.log(arr[i]);
// for in 可以遍历对象 和数组
}
hasOwnProperty
// hasOwnProperty
// 拷贝的问题
let obj = {
name: "张三",
age: 18,
};
//obj.hasOwnProperty(obj.name); 不是false 就是 true
function Car() {
this.brand = "Benz";
this.color = "red";
this.displacement = "3,0";
}
Car.prototype = {
lang: 5,
width: 2.5,
};
let car = new Car();
for (let key in car) {
console.log(key + ":" + car[key]);
// 原型上只要是自己设置的属性都会被打印出来(上层所有原型)
}
for (let key in car) {
if (car.hasOwnProperty(key)) {
console.log(car[key]);
}
// 找自身的属性不找原型上的属性
}
instanceof
// instanceof 非常重要
// 题是肯定要靠的
// 判断这个对象是否是该构造函数实例出来的
function Car() {}
let car = new Car();
console.log(car instanceof Car); // true
function Person() {}
let p = new Person();
console.log(p instanceof Car); // false
console.log(car instanceof Object); // true
console.log([] instanceof Array); // true
console.log([] instanceof Object); // true
// A对象的原型里到底有没有B的原型 在原型链里面只要他们重合的 结果都是true
Object.prototype的toString方法实际开发中的用法
let a = [] || {};
console.log(a.constructor); // Array()
console.log(a instanceof Array); // true
let str = Object.prototype.toString.call(a);
if (str === "[object Array]") {
console.log("是数组");
} else {
console.log("不是数组");
}
// 实际开发经常用到,后端传来的数据做判断
{
let str = Object.prototype.toString,
trueTip = "[object Array]";
if (str.call(a) === trueTip) {
console.log();
}
}
console.log(str); //[object Array]
复习this练习题
- 第一题
// 函数内部的this指向谁
function test(b) {
this.d = 3; // window.d = 3
let a = 1;
function c() {}
}
test(123);
/* AO = {
arguments: [123]
this: window,
b: 123,
a: undefined,
c: function c(){}
} */
// 函数内部的this在函数没运行时指向的是window
// 此时的this.d 相当于window.d
- 第二题
function Test() {
//var this = {
// __proto__: Test.prototype
// }
this.name = "123";
}
let test = new Test();
/* AO ={
this: window -> {
name: '123',
__proto__: Test.prototype
}
}
GO = {
Test: function test(){...}
test: {}
} */
apply练习题
function Person() {
this.name = "张三";
this.age = 18;
}
function Programmer() {
Person.apply(this);
this.work = "Programming";
}
let p = new Programmer();
console.log(p);
// 全局this -> window
// 预编译函数 this -> window
// apply / call 改变this指向
// 构造函数的this指向实例化对象
callee/caller
//caller
function test() {
console.log(arguments.callee.length);
}
test(); // 0
function test1(a, b, c) {
console.log(arguments.callee.length); // 返回实参指向的函数长度
console.log(test.length); // 函数形参长度
console.log(arguments.length); // 实参长度;
}
test(1, 2, 3); // 3
//arguments.callee
// 返回的是正在被执行的函数对象 执行到这一句 arguments指向的函数是谁就返回
{
function test2() {
console.log(arguments.callee);
function test3() {
console.log(arguments.callee);
}
test3();
}
test2();
// 打印出两个函数
}
/* function sum(n) {
if (n <= 1) {
return 1;
}
return n + sum(n - 1);
}
let res = sum(10);
console.log(res); // 55 */
let sum = (function (n) {
if (n <= 1) {
return 1;
}
return n + arguments.callee(n - 1);
// callee 不是找函数名 而是找这个函数
})(10);
console.log(sum);
// caller
function test1() {
test2();
}
test1();
function test2() {
console.log(test2.caller);
// 返回当前被调用函数的函数引用
// 所以放回test1 因为 是test1调用的test2
// 必须被调用了才打印得出来
}
- 严格模式下 这两个属性不能用
面试题
// 阿里机答题
function foo() {
bar.apply(null, argument); // 相当于没有指定this
}
function bar() {
console.log(arguments);
}
// bar() = bar.call(arguments) -> bar(arguments)
foo(1, 2, 3, 4, 5); // [1,2,3,4,5]
//JS的typeof可能返回的值有哪些?
// 'undefined' 'object(Null)' 'boolean' 'number' 'string' 'function'
function b(x, y, a) {
arguments[2] = 10;
alert(a); // 弹10
a = 10;
alert(arguments[2]); // 还是弹10 形参和实参有映射关系 在函数内改两者都会改变
}
b(1, 2, 3);
alert(123);
let f =
(function f() {
return "1";
},
function g() {
return 2;
});
console.log(typeof f); // 'Function'
undefined == null; //true
undefined === null; // false
isNaN("100"); // false 隐式转换成了数字
parseInt("1a") == 1; // true
function isNaN2(num) {
let res = Number(num); // 这里把结果转换为字符串 加一个空字符串符号
if (res == NaN) {
// NaN不等于任何数 所以有问题 这里要判断字符串的NaN才行
return true;
} else {
return FontFaceSetLoadEvent;
}
}
console.log(isNaN2("123"));
undefined == null; //true
undefined === null; // false
isNaN("100"); // false 隐式转换成了数字
parseInt("1a") == 1; // true
function isNaN2(num) {
let res = Number(num); // 这里把结果转换为字符串 加一个空字符串符号
if (res == NaN) {
// NaN不等于任何数 所以有问题 这里要判断字符串的NaN才行
return true;
} else {
return FontFaceSetLoadEvent;
}
}
console.log(isNaN2("123"));
// 面试题
// {} == {} : 不等于
// 为什么不等于 :引用值对比的是地址 这是两个不同的对象存的地址都不同
// 怎么让两个对象相等 let obj = {}; obj1 = obj 这样两个对象就相等了
let a = "1";
function test() {
let a = "2";
this.a = "3";
console.log(a);
}
test(); // 2
new test(); // 2
console.log(a); // 3
\