wuyunqiang / performance-js Goto Github PK
View Code? Open in Web Editor NEWjs高级程序设计
js高级程序设计
1:数据属性
[[configurable]]:表示能否delete删除属性,默认为true
[[enumerable]]:能否通过in迭代访问
[[writable]]:能否修改属性值
[[value]]:包含这个属性的数据值,读取和访问时都说该值,默认undefined。
2:访问器属性
[[get]]:读取属性时调用,默认值undefined。
[[set]]:写入属性时调用,默认值undefined。
1:定义属性特性
object.defineProperty();
object.defineProperties();
2:读取属性特性
object.getOwnPropertydescriptor()
1:获得对象实例,
2:共享对象方法,
3:属性为每个实例私有,
4:实例可以判断类型
5:可以配置参数初始化
function createPerson(name) {
var o = new Object();
o.name = name;
o.sayName = function () {
console.log(this.name)
}
return o;
}
//1满足 每次调用返回一个新对象
//3满足 属性为每个实例私有
//5满足
//4不满足 对象都是object类型 不能对象识别,
//2不满足 方法不能共享
//要知道sayName是一个函数,函数也是一种对象,
// 所以以上方式创建了一个o对象和一个赋值sayName的匿名对象,如果有多个方法,那么每次都会新建n(方法数)+1个对象,对象会占据内存,因此内存开销太大。
function Person(name) {
this.name = name;
this.sayName = function () {
console.log(this.name)
}
}
let p = new Person("wye");
//直接将属性和方法赋值给this
//通过new 创建一个新对象
//将构造函数的作用域给新对象(this指向新对象)
//执行构造函数 给this添加属性方法
//返回this
//1,3,4(p instance Person),5 满足,
//2不满足
// 可以换一种写法等效
o.sayName = new function () {
console.log(this.name)
}
//写法一:
function Persion() {}
Persion.prototype.name = "wyq";
Persion.prototype.friends = ["a","b","c"];
Persion.prototype.sayName = function () {
console.log("this.name",this.name);
};
let p = new Persion();
//写法二:重写对象原型
function Persion() {}
var p = new Persion();
Persion.prototype = {
name: "wyq",
friends: ["a", "b", "c"],
sayName: function () {
console.log("this.name", this.name);
},
};
var m = new Persion();
p.friends.push("d"); //P访问不到 m可以访问
//因为p.constructor= Persion 在实例化时就确定了指向,
//而在重写原型对象以后实例化的m.constructor指向的是
//匿名对象 即
object= {
name: "wyq",
friends: ["a", "b", "c"],
sayName: function () {
console.log("this.name", this.name);
},
};
console.log("m",m.friends);
//注意:原型的属性和方法是动态添加以后所有实例都可以访问的,
//但是实例与原型的指向关系是静态的,在实例化时就确定的,
//当实例已经存在时,重新覆盖原型会切断已经实例化的对象与原型的关系。
问题:
//3,5不满足
//如果属性是一个引用类型的对象friends,改变一个实例所有实例属性都会发生变化。
function Persion() {}
Persion.prototype.name = "wyq";
Persion.prototype.friends = ["a","b","c"];
Persion.prototype.sayName = function () {
console.log("this.name",this.name);
};
var p = new Persion();
var m = new Persion();
p.friends.push("d");
console.log("m",m.friends); //["a","b","c","d"]
//将私有属性放到构造函数里面,将共享属性放到原型上面
//方法一
function Persion() {
this.name="wyq";
this.friends=["a", "b", "c"];
}
Persion.prototype = {
sayName: function () {
console.log("this.name", this.name);
},
};
function SuperType() {
this.colors = ["a","b","c","d"];
}
SuperType.prototype.getColor = function (i) {
return this.colors[i];
};
function SubType() {}
SubType.prototype = new SuperType();
let sub1 = new SubType();
let sub2 = new SubType();
sub1.colors.push("e");
console.log("sub1.getColor(1)",sub1.getColor(1));
console.log("sub2.colors",sub2.colors);
//缺点:
//1:子类所有实例,共享父类属性。
//2:没有办法在不影响所有子类实例的情况下给超类传递参数
//只需修改子类构造如下
function SubType() {
SuperType.call(this); //实例属性私有化
this.size = "15"//定义子类自己的属性
}
sub1.colors.push("e");
console.log("sub1.colors",sub1.colors);//["a", "b", "c", "d", "e"]
console.log("sub2.colors",sub2.colors);//["a", "b", "c", "d"]
方式二会调用两次超类的构造函数,一次在创造子类原型,一次在子类构造函数内部。
function inherit(subType,superType) {
var prototype = {...superType.prototype}
prototype.constructor = subType;//将子类实例构造指向子类 否则为父类
subType.prototype = prototype;
}
function SuperType() {
this.colors = ["a","b","c","d"];
}
SuperType.prototype.getColor = function (i) {
return this.colors[i];
};
function SubType() {
SuperType.call(this); //实例属性私有化
this.size = "15"//定义自己的属性
}
// SubType.prototype = SuperType.prototype; 这种方式子类实例构造指向父类
inherit(SubType,SuperType);
let sub1 = new SubType();
let sub2 = new SubType();
sub1.colors.push("e");
console.log("sub1.construnct",sub1.constructor);
Object.create()
es6 扩展运算符...
一声明:
函数声明,存在声明提升
函数表达式
二内部对象:
每个函数都有this,argments两个对象。
apply call bind 内部方法
参数传递是值传递
三执行环境:
1:作用域 =>保存当前和父环境活动对象的指针数组
2:活动对象=>argments,声明的变量
3:this=>动态改变
四闭包:
访问函数内部私有变量
延迟变量声明周期,
模仿块级作用域,
共享变量。
形式1:
function f() {
var arr = [];
for (var i=0;i<10;i++){
arr[i] = function () {
console.log(i);//访问函数内部私有变量
}
}
return arr;
}
var arr = f();
console.log("arr",arr[7]()); //10
形式2:
function f() {
var arr = [];
for (var i=0;i<10;i++){
arr[i] = function (index) {//访问函数内部私有变量 延迟储存变量i
return function () {
console.log(index);
}
}(i)
}
return arr;
}
var arr = f();
console.log("arr",arr[7]()); //7
形式3:
function f() {
var count = 5;
(function () {//模仿块级作用域,
for(var i=0;i<count;i++){//访问函数内部私有变量
console.log(i)
}
})()
}
形式4:
(function () {
var name = "wyq";
Person = function () {}//作为类使用
Person.prototype.setName=function (n) {
name = n;
};
Person.prototype.getName = function () {
return name;
}
})();
/**
* 代码作用:
* 1:声明一个Person类
* 2:初始化Person原型添加setName,getName方法
* 3:模仿块级作用域
* 4:通过闭包的方式在Person类外面嵌套一个匿名函数,使Person可以访问name属性
* 5:所有Person实例共享name属性,适合单例使用*/
五函数是什么:
函数是对象
函数是方法
函数是类
函数是函数
function MyObject() {
var name ="wyq";
function getName() {//私有函数
return name;
}
this.publicMethod = function () {//公有方法
return getName();
}
this.age = 'asd'//公有属性 是对象
}
var obj = new MyObject();//函数是类
console.log('obj.age',obj.age)
console.log('obj.age',obj.publicMethod())
js函数为什么没有重载?
因为函数的本质是一种对象,函数名字重复相当于变量的重新赋值。
function MyObject() {
var name ="wyq";
console.log('name',name);
}
等价于:
var MyObject = function () {
var name ="wyq";
console.log('name',name);
}
所以同名函数如下:
function MyObject() {
console.log('hello');
}
var MyObject = function () {
console.log('hello');
}
1:typeof只能判断基本数据类型(null object = object)
2:Object.prototype.toString判断基本类型,复合类型返回 字符串:[object xxx类型]
3:实例判断instanceof x instanceof X 返回布尔型
function type(obj) {
let class2type = {};
// 生成class2type映射
"Boolean Number String Function Array Date RegExp Object Error".split(" ").map(function(item, index) {
class2type["[object " + item + "]"] = item.toLowerCase();
})
// 一箭双雕 undefined null 值相等 类型不等
if (obj == null) {
return obj + "";
}
// 优先ES6方法判断数组类型
if(Array.isArray(obj)){
return "array"
}
return typeof obj === "object" || typeof obj === "function" ?
class2type[Object.prototype.toString.call(obj)] || "object" :
typeof obj;
}
当参数有多个的时候可以多次的部分输入 最后输入参数为空时调用函数。
利用闭包保存参数
每次返回一个函数
testCurry = (args)=>{
args.pop();//去掉最后一个参数undefined
if(args.length<1){
return;
}
let sum = args.reduce((s,n)=>{
return s+n;
},0);
console.log('参数',args);
console.log('sum',sum);
return sum;
};
//一版本
// curry = fn => {
// let arr = [];
// judge = (...args)=>{
// if(!args[args.length-1]){
// return fn(arr);
// }else{
// arr.push(...args);
// return judge;
// }
// };
// return judge;
// }
//二版本
// curry = fn => judge=(...args)=>{
// if(!args[args.length-1]){
// return fn(args);
// }else{
// return (...arg)=>{
// return judge(...args,...(temp=arg.length<1?[null]:arg));
// };
// }
// }
//三版本
curry = fn =>judge=(...args)=>!args[args.length-1]?fn(args):(...arg)=>judge(...args,...(temp=arg.length<1?[null]:arg))
OnClick =()=>{
console.log('执行了这里 OnClick');
let one = this.curry(this.testCurry)(1);
let two = one(2)(3)(4)(5);
let three = two(6,6,6);
three();
};
#一 :四种绑定规则
优先级由高到低顺序
1:new 绑定
var o = {
m: function(){
return this;
}
}
var obj = new o.m();//obj为新产生的对象
console.log(obj,obj === o);//{} false
console.log(obj.constructor === o.m);//true
2:显示绑定
通过call apply bind实现
var a = 0;
function foo(){
console.log(this.a);
}
var obj1 = {
a:1
};
var obj2 = {
a:2
};
foo.call(obj1);//1
foo.call(obj2);//2
3:隐式绑定
function foo(){
console.log(this.a);
};
var obj1 = {
a:1,
foo:foo,
}
//foo()函数的直接对象是obj1,this隐式绑定到obj1
obj1.foo();//1
4:默认绑定
//虽然test()函数被嵌套在obj.foo()函数中,但test()函数是独立调用,而不是方法调用。所以this默认绑定到window
var a = 0;
var obj = {
a : 2,
foo:function(){
function test(){
console.log(this.a);
}
test();
}
}
obj.foo();//0
#二:箭头函数绑定
箭头函数的绑定规则只与作用域有关,箭头函数会继承外层函数调用的this绑定
#三:函数嵌套
函数嵌套中内部和外部函数相互独立调用没有this继承关系,
方法嵌套内部方法会继承外部函数的this指向。
function f3() {
console.log('f3 this',this);//全局对象
}
export default class Page1 extends Component {
constructor(props){
super(props);
}
test=()=>{
//箭头函数内部指向Page1 class
console.log('test this',this);
let obj={
f1:function () {
console.log('obj f1 this',this); // 指向obj
function f() {
console.log('obj f this',this);
}
f(); //函数的嵌套不存在this的继承 内部f和外部f1 相互独立 因此内部f全局对象 外部f1指向obj对象
f3();//内嵌的函数不存在this的继承关系 因此调用f3的是全局对象
this.f2(); //方法的嵌套是可以继承this的 即内部的方法可以继承外部方法的this
},
f2:function () {
console.log("obj f2 this",this)
}
}
obj.foo();
};
test2(){
//不是箭头函数 指向调用它的对象这里为touch组件
console.log('test2 this',this);
// this.countdown();//报错
}
countdown(){
console.log('countdown this',this);
}
render(){
return (
<View style={styles.container}>
<TouchableOpacity style={styles.touchstyle} activeOpacity={0.7} onPress={this.test}>
<View style={styles.viewstyle}>
<Text style={{fontSize:FONT(39/2),backgroundColor:'transparent',textAlign:'center'}}>test</Text>
</View>
</TouchableOpacity>
<TouchableOpacity style={styles.touchstyle} activeOpacity={0.7} onPress={this.test2}>
<View style={styles.viewstyle}>
<Text style={{fontSize:FONT(39/2),backgroundColor:'transparent',textAlign:'center'}}>test2 this指向touch组件</Text>
</View>
</TouchableOpacity>
</View>
)
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.