目录
构造函数不用new修饰,当做普通函数使用,返回undefined
构造函数不用new修饰,当做普通函数使用,返回undefined
function People(age,name) { console.log(this) this.name = name; this.age = age; } var p1 = People(20,"张三"); console.log(p1);
严格模式:"use strict";
JavaScript 严格模式(use strict) | 菜鸟教程
在严格模式下this指向undefined
function f(){ return !this; } // 返回false,因为"this"指向全局对象,"!this"就是false function f(){ "use strict"; return !this; } // 返回true,因为严格模式下,this的值为undefined,所以"!this"为true。
1.对象的补充:
Object.definePropertype()
其中Vue就通过这个方法来实现监听数据的改变和读取(属性中的getter和setter方法)实现数据劫持
可以直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象
Object.defineProperty(obj, prop, descriptor);
p1: obj:需要操作的对象
p2: prop:需要操作的属性
p3: descriptor:属性描述符
(value值,writable可写性,configurable可删除性,enumerable可枚举性--可迭代性
set(),get()方法,
注意:当使用了getter或setter方法,不允许使用writable和value这两个属性(如果 使用,会直接报错滴))
let obj = {}; let oldValue = '李白'; Object.defineProperty(obj, 'name', { // value: oldValue, // writable: true, configurable: true, enumerable: true, get(){ console.log("get is executed"); return oldValue; }, set(newValue){ if(oldValue !== newValue){ console.log("set is executed"); oldValue = newValue; } } }); console.log(obj.name); obj.name = 'lnj'; console.log(obj.name);//lnj
Object.assign() 把可以枚举的属性从一个对象中合并到目标对象中 返回的是目标对象
assign方法为浅拷贝
// assign 分配 // 把可以枚举的属性从一个对象中合并到目标对象中 返回的是目标对象 var target = { name: "zs", age: 20 } var source = { gf: 10, address: "二七区嵩山路街道", box: { money: 1000, card: 5 } } var obj = Object.assign(target, source); source.gf = 1;//基本数据类型 相互之间没有影响 // assign 方法为浅拷贝 source.box.money = 1;// source 更改影响target中的数据 console.log("obj = ", obj); console.log('target =', target); // console.log(obj === target);// true
// 合并对象的属性
var source = { name: "zhagnsan" };
var obj = Object.assign({}, source)
// 合并数组,将索引值相同的替换掉
var array = [1, 2, 4, 5, 6];
// 数组的替换
console.log(Object.assign(array, [100, 200, 300]));// [100, 200, 300, 5, 6]
var o1 = { x: 1, y: 2, z: 3 };
var o2 = { y: 4, z: 6 };
var o3 = { z: 10 }
var obj = Object.assign({}, o1, o2, o3); //{x:1,y:4,z:10}
console.log(obj);
// 4. keys values entries is
var obj = {
name:"zhangsna",
age:20
}
var keyArray = Object.keys(obj);//所有的key组成的数组
console.log(keyArray);
var values = Object.values(obj);
console.log(values);
//
Object.entries()
方法返回一个给定对象自身可枚举属性的键值对数组,二维数组var entries = Object.entries(obj);
console.log(entries)
// 判断是否为同一个对象
// Object.is() 方法判断两个值是否为同一个值。
console.log(Object.is([1],[1]))//false
对象的扩充,密封,冻结(都是静态方法)
2.定义对象的方法:
js创建对象的6种方式总结_Jeffrey Dean的博客-CSDN博客_nodejs创建对象
字面量{},用new关键字+Object(),工厂模式,构造函数,原型,构造函数+原型:通过这几种方式创建出来的对象都没有属性的配置项,对其属性可以直接修改,删除,枚举出来。
可以用对象的静态方法Object.creat()来创建对象,使现有的对象来作为新创建对象的原型
参数1:指定的原型对象
参数2:属性的配置项 value值 writable可修改,configurable可配置删除,enumerable可枚举(可遍历,迭代)
阻止对象的扩充:
Object.preventExtensions(obj1);
判断对象是否被阻止扩充:
Object.isExtensible(obj1);
对象的密封 seal
1.不能添加
2.可以修改(必须配置writable:true)
3.不能删除 (配置为configurable true 也不行)
Object.seal(obj2);// 密封对象
查看对象是否被密封 返回值为bool
Object.isSealed(obj2);
对象的冻结 freeze
1.不能添加
2.不能修改
3.不能删除
Object.freeze(obj3);
console.log(Object.isFrozen(obj3))//冻住了
set,get设置操作对象的属性值
3.模块化: 通过立即执行函数+闭包实现
将一个复杂的程序依照一定的规则封装成几个文件并进行组合在一起,每个模块的内部数据是私有的,只是向外部暴露一些接口(方法)与外部其他模块通信。
优点:避免命名空间的冲突
更好的分离,实现按需加载
提高代码的复用性
提高代码的维护性
将方法赋值给window对象 设置为全局方式 ——缺点:全局变量的污染
fn(); window.fn = function () { console.log("module中的方法"); }
变量无法私有化 外部可以修改内部函数的变量
mObj.num = 1000; mObj.fn(); mObj = { num: 0, fn: function () { this.num++; console.log(" ==== ", this.num); } }
通过立即执行函数+闭包实现模块化
(jquery源码最外层就是一个立即执行函数)
mObj2.fn(); mObj2.play();// 报错 没有play方法 mObj2 = (function () { var num = 0; function fn() { console.log("======",++num + num2); } var num2 = play(); function play() { console.log("打篮球去吧 不qu!!!"); return 100; } // 当key 和value 名称相同时 直接写名称 return { // fn:fn fn } }())
4.扩充 数组,juqery的方法 的实现
扩充数组的方法 将方法设置在其原型对象中,所有数组对象都可以调用该方法
Array.prototype.todosomthing = function () {
console.log("逻辑");
}
var ar = [];
ar.todosomthing();
var ar1 = [];
ar1.todosomthing();
扩充jquery的方法:通过extend()方法实现
$.extend({
money:100,
todosomthing(){
console.log("to do something");
}
})
console.log($.money);
$.todosomthing();
5.模拟实现jQueryAjax方法的封装
通过立即执行函数,传递一个对象,封装对象的ajax方法,最后返回一个对象,这个对象就拥有ajax方法,同时让$也等于这个对象,$也能使用ajax方法
var jQuery=(function (jq) {
jq.ajax=function (obj) {
var xhr=new XMLHttpRequest;
xhr.open(obj.type || "get", obj.type === "get" ? obj.url + obj.data : obj.url);
xhr.send(obj.type==="get"?null:obj.data);
xhr.onreadystatechange=function () {
if(xhr.readyState==4&&xhr.status==200){
obj.success(JSON.parse(xhr.responseText));
}
}
}
window.$=jq;
return jq;
}({}))
6、js模块的放大模式:
脚本引入有顺序 在一个模块的基础上扩充更多的方法
例如purl,validate的脚本是在引入jquery脚本的基础上再引入
将第一个脚本中的对象作为第二个脚本立即执行函数的参数,在函数中扩充新方法,最后将含有新方法的对象返回出去,这样第一个脚本中的对象就拥有这个新方法啦!
// 放大模式 类似继承 在m1的基础上扩充更多的方法 但不是继承
// 先引入jquery 再 purl validate
// 在放大模式下 脚本引入是有序的
// 而宽放大模式是没有顺序的
var m1 = (function() {
var sayHi = function () {
console.log("hi");
}
return {
sayHi
}
}())
var m2 = (function(m){
m.sayHi();
// 扩充新方法
m.play = function () {
console.log(" 新 方法...");
}
var m2Method = function () {
console.log("m2 的新方法")
}
return {
m2Method
}
})(m1)
宽放大模式: 还是实现对一个模块进行扩充方法,但不受脚本引入顺序的影响
在脚本中给对象赋一个立即执行函数,参数为这个对象或一个空对象,给对象添加方法后再返回这个对象,
// 还是想对m1进行扩充 脚本引入则没有顺序了 宽放大模式
var m1 = (function (m) {
var sayHi = () => {
console.log("hi");
}
m.sayHi = sayHi;
return m
})(m1 || {})